From 9e6fa4501db1f9e301f35fadac69db83b921b806 Mon Sep 17 00:00:00 2001 From: Kumi Date: Wed, 19 Jul 2023 08:25:41 +0200 Subject: [PATCH 1/2] Add Destructables mention --- README.md | 17 ++++++++++++++--- templates/footer.html | 3 ++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2e8d058..7aee3e7 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,23 @@

Indestructables

-An open source alternative front-end to Instructables. This is a fork of snowcatridge10's Indestructables to use Playwright instead of Selenium. +An open source alternative front-end to Instructables. This is a fork of snowcatridge10's Indestructables to use Playwright instead of Selenium, which itself is a fork of Cobra's Destructables. -snowcatridge10's Matrix Room +
# Instances | URL | Provided by | Country | Comments | -|------------------------------------------------------------------------------------|-------------------------------------------|---------|----------| +| ---------------------------------------------------------------------------------- | ----------------------------------------- | ------- | -------- | | [https://indestructables.private.coffee/](https://indestructables.private.coffee/) | [Private.coffee](https://private.coffee/) | Austria | | # Run your own instance @@ -36,3 +43,7 @@ Furthermore, you need to install the Chromium binary used by Playwright. You can 1. Clone the repository 2. Run `python3 main.py` 3. Connect to http://localhost:8002 + +## License + +This project, as well as the two projects it is based on, are licensed under the GNU Affero General Public License v3. See the LICENSE file for more information. \ No newline at end of file diff --git a/templates/footer.html b/templates/footer.html index debc6e9..c82563e 100644 --- a/templates/footer.html +++ b/templates/footer.html @@ -2,7 +2,8 @@

Modified Source Code (AGPLv3)

-

Original Source Code (AGPLv3)

+

Original Indestructables Source Code (AGPLv3)

+

Original Destructables Source Code (AGPLv3)

View privacy policy.

\ No newline at end of file From e09497f47149719f936634677a098b47835fd32e Mon Sep 17 00:00:00 2001 From: Kumi Date: Wed, 19 Jul 2023 08:26:45 +0200 Subject: [PATCH 2/2] Improve error handling --- main.py | 60 ++++++++++++++++++++++------------------------ templates/500.html | 21 ++++++++++++++++ 2 files changed, 50 insertions(+), 31 deletions(-) create mode 100644 templates/500.html diff --git a/main.py b/main.py index f6022cd..fbb67e5 100644 --- a/main.py +++ b/main.py @@ -8,8 +8,10 @@ from flask import ( Response, stream_with_context, ) + import requests import re + from bs4 import BeautifulSoup from urllib.parse import quote, unquote from traceback import print_exc @@ -18,6 +20,8 @@ from playwright.sync_api import sync_playwright from urllib.parse import urljoin from argparse import ArgumentParser +from werkzeug.exceptions import BadRequest, abort, InternalServerError, NotFound + import os global_ibles = {} @@ -258,9 +262,7 @@ def member_header(header): def category_page(path, name, teachers=False): 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 - ) + abort(data.status_code) soup = BeautifulSoup(data.text, "html.parser") @@ -417,9 +419,7 @@ def project_list(path, head, sort=""): def route_sitemap(): data = requests.get(f"https://www.instructables.com/sitemap/") if data.status_code != 200: - return Response( - render_template(str(data.status_code) + ".html"), status=data.status_code - ) + abort(data.status_code) soup = BeautifulSoup(data.text, "html.parser") @@ -446,9 +446,7 @@ def route_contest_archive(): page = request.args.get("page") data = requests.get(f"https://www.instructables.com/contest/archive/?page={page}") if data.status_code != 200: - return Response( - render_template(str(data.status_code) + ".html"), status=data.status_code - ) + abort(data.status_code) soup = BeautifulSoup(data.text, "html.parser") @@ -485,9 +483,7 @@ def route_contest_archive(): def route_contest(contest): data = requests.get(f"https://www.instructables.com/contest/{contest}/") if data.status_code != 200: - return Response( - render_template(str(data.status_code) + ".html"), status=data.status_code - ) + abort(data.status_code) soup = BeautifulSoup(data.text, "html.parser") @@ -541,9 +537,7 @@ def route_contest(contest): def route_contests(): data = requests.get("https://www.instructables.com/contest/") if data.status_code != 200: - return Response( - render_template(str(data.status_code) + ".html"), status=data.status_code - ) + abort(data.status_code) soup = BeautifulSoup(data.text, "html.parser") @@ -668,9 +662,7 @@ def route_sitemap_circuits(category, subcategory): def route_member_instructables(member): data = requests.get(f"https://www.instructables.com/member/{member}/instructables") if data.status_code != 200: - return Response( - render_template(str(data.status_code) + ".html"), status=data.status_code - ) + abort(data.status_code) soup = BeautifulSoup(data.text, "html.parser") @@ -709,9 +701,7 @@ def route_member(member): f"https://www.instructables.com/member/{member}/", headers=headers ) if data.status_code != 200: - return Response( - render_template(str(data.status_code) + ".html"), status=data.status_code - ) + abort(data.status_code) soup = BeautifulSoup(data.text, "html.parser") @@ -765,9 +755,7 @@ def route_member(member): def route_article(article): data = requests.get(f"https://www.instructables.com/{article}/") if data.status_code != 200: - return Response( - render_template(str(data.status_code) + ".html"), status=data.status_code - ) + abort(data.status_code) soup = BeautifulSoup(data.text, "html.parser") @@ -948,7 +936,7 @@ def route_article(article): except Exception: print_exc() - return Response(render_template("404.html"), status=404) + raise InternalServerError() @app.route("///") @@ -964,16 +952,14 @@ def route_channel_redirect(category, channel): ): return redirect(f"/{category}/{channel}/projects/", 307) else: - return Response(render_template("404.html"), status=404) + raise NotFound() @app.route("/") def route_explore(): data = requests.get("https://www.instructables.com/") if data.status_code != 200: - return Response( - render_template(str(data.status_code) + ".html"), status=data.status_code - ) + abort(data.status_code) soup = BeautifulSoup(data.text, "html.parser") @@ -1011,9 +997,9 @@ def route_proxy(): data = requests.get(unquote(url)) return Response(data.content, content_type=data.headers["content-type"]) else: - return Response(render_template("400.html"), status=400) + raise BadRequest() else: - return Response(render_template("400.html"), status=400) + raise BadRequest() @app.route("/privacypolicy/") def privacypolicy(): @@ -1023,5 +1009,17 @@ def privacypolicy(): def not_found(e): return render_template("404.html") +@app.errorhandler(400) +def bad_request(e): + return render_template("400.html") + +@app.errorhandler(429) +def too_many_requests(e): + return render_template("429.html") + +@app.errorhandler(500) +def internal_server_error(e): + return render_template("500.html") + if __name__ == '__main__': app.run(port=args.port, host=args.listen_host, debug=debugmode) diff --git a/templates/500.html b/templates/500.html new file mode 100644 index 0000000..797429f --- /dev/null +++ b/templates/500.html @@ -0,0 +1,21 @@ + + + + + 500 - Indestructables + + + {% include "style.html" %} + + + + + {% include "header.html" %} +
+

500

+

An internal server error has occurred. Please try again later, or notify the administrator if this keeps happening.

+
+ {% include "footer.html" %} + + + \ No newline at end of file