💾 Archived View for gmn.clttr.info › sources › geminispace.info.git › tree › serve › views.py.txt captured on 2023-06-14 at 14:31:34.

View Raw

More Information

⬅️ Previous capture (2023-04-20)

➡️ Next capture (2023-09-08)

🚧 View Differences

-=-=-=-=-=-=-

import math
import os
from datetime import datetime
from urllib.parse import quote, unquote

import jinja2
from jetforce import Request, Response, Status, JetforceApplication

from . import constants
from .models import (
    compute_verbose,
    compute_requested_results_page,
    GUS,
    process_seed_request,
)
from gus.excludes import EXCLUDED_URL_PREFIXES, EXCLUDED_URL_PATHS

TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), "templates")

template_env = jinja2.Environment(
    loader=jinja2.FileSystemLoader(TEMPLATE_DIR),
    undefined=jinja2.StrictUndefined,
    trim_blocks=True,
    lstrip_blocks=True,
)


def datetimeformat(value, format="%Y-%m-%d"):
    return value.strftime(format)


template_env.filters["datetimeformat"] = datetimeformat


def render_template(name: str, *args, **kwargs) -> str:
    """
    Render a gemini directory using the Jinja2 template engine.
    """
    return template_env.get_template(name).render(*args, **kwargs)


app = JetforceApplication()
gus = GUS()


@app.route("/status", strict_trailing_slash=False)
def status(request):
    return Response(Status.SUCCESS, "text/plain", "ok")

@app.route("/robots.txt", strict_trailing_slash=False)
def status(request):
    return Response(Status.SUCCESS, "text/plain",
            """User-agent: researcher
User-agent: indexer
User-agent: archiver
Disallow: /v/search
Disallow: /searce
Disallow: /backlinks

User-agent: *
Disallow: /add-seed
""")

@app.route("/favicon.txt", strict_trailing_slash=False)
def favicon(request):
    return Response(Status.SUCCESS, "text/plain", "🔭")


@app.route("/add-seed", strict_trailing_slash=False)
def add_seed(request):
    if request.query:
        process_seed_request(request.query)
        body = render_template("add_seed.gmi", seed_url=request.query)
        return Response(Status.SUCCESS, "text/gemini", body)
    else:
        return Response(Status.INPUT, "Gemini URL")


@app.route("/statistics", strict_trailing_slash=False)
def statistics(request):
    body = render_template(
        "statistics.gmi",
        statistics=gus.statistics,
        index_modification_time=gus.statistics["index_modification_time"]
    )
    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("/statistics/historical/overall", strict_trailing_slash=False)
def statistics(request):
    body = render_template(
        "statistics_historical_overall.gmi",
        statistics_historical_overall=gus.statistics_historical_overall[::-1],
        index_modification_time=gus.statistics["index_modification_time"]
    )
    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("/known-hosts", strict_trailing_slash=False)
def known_hosts(request):
    body = render_template(
        "known_hosts.gmi",
        known_hosts=gus.hosts,
        index_modification_time=gus.statistics["index_modification_time"]
    )
    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("/newest-hosts", strict_trailing_slash=False)
def newest_hosts(request):
    body = render_template(
        "newest_hosts.gmi",
        newest_hosts=gus.newest_hosts,
        index_modification_time=gus.statistics["index_modification_time"]
    )
    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("/newest-pages", strict_trailing_slash=False)
def newest_pages(request):
    body = render_template(
        "newest_pages.gmi",
        newest_pages=gus.newest_pages,
        index_modification_time=gus.statistics["index_modification_time"]
    )
    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("/known-feeds", strict_trailing_slash=False)
def known_feeds(request):
    body = render_template(
        "known_feeds.gmi",
        known_feeds=gus.feeds,
        index_modification_time=gus.statistics["index_modification_time"]
    )

    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("", strict_trailing_slash=False)
def index(request):
    body = render_template(
        "index.gmi",
        index_modification_time=gus.statistics["index_modification_time"]
    )
    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("/about", strict_trailing_slash=False)
def index(request):
    body = render_template(
        "about.gmi",
        index_modification_time=gus.statistics["index_modification_time"]
    )
    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("/documentation/searching", strict_trailing_slash=False)
def documentation_searching(request):
    body = render_template(
        "documentation/searching.gmi",
        index_modification_time=gus.statistics["index_modification_time"]
    )
    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("/documentation/indexing", strict_trailing_slash=False)
def documentation_indexing(request):
    body = render_template(
        "documentation/indexing.gmi",
        index_modification_time=gus.statistics["index_modification_time"]
    )
    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("/documentation/filters", strict_trailing_slash=False)
def documentation_filters(request):
    body = render_template(
        "documentation/filters.gmi",
        index_modification_time=gus.statistics["index_modification_time"],
        filters=sorted(EXCLUDED_URL_PREFIXES)
    )
    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("/documentation/backlinks", strict_trailing_slash=False)
def documentation_backlinks(request):
    body = render_template(
        "documentation/backlinks.gmi",
        index_modification_time=gus.statistics["index_modification_time"]
    )
    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("/news", strict_trailing_slash=False)
def index(request):
    body = render_template(
        "news.gmi",
        index_modification_time=gus.statistics["index_modification_time"]
    )
    return Response(Status.SUCCESS, "text/gemini", body)


@app.route("/v/search(/\d+)?")
@app.route("/search(/\d+)?")
def search(request):
    if request.query:
        verbose = compute_verbose(request.path)
        requested_page = compute_requested_results_page(request.path)
        num_results, results = gus.search_index(request.query, requested_page)
        #if num_results > 0:
        num_pages = math.ceil(num_results / 10)
        current_page = min(requested_page, num_pages)
        if num_results == 0:
            current_page = 0
        body = render_template(
            "search.gmi",
            query=request.query,
            quoted_query=quote(request.query),
            verbose=verbose,
            num_results=num_results,
            results=results,
            current_page=current_page,
            num_pages=num_pages,
            index_modification_time=gus.statistics["index_modification_time"]
        )
        #else:
            #    search_suggestions = gus.get_search_suggestions(request.query)
            #    body = render_template(
            #        "search_suggestions.gmi",
            #        query=request.query,
            #        search_suggestions=search_suggestions,
            #        index_modification_time=gus.statistics["index_modification_time"]
            #    )

        return Response(Status.SUCCESS, "text/gemini", body)
    else:
        return Response(Status.INPUT, "Search query")


@app.route("/search/jump/(?P<query>.+)")
@app.route("/v/search/jump/(?P<query>.+)")
def search_jump(request, query):
    if request.query:
        if request.query.isdigit():
            jump_page = request.query
        else:
            jump_page = 1
        verbose_segment = "/v" if request.path.startswith("/v") else ""
        jump_url = f"{verbose_segment}/search/{jump_page}?{query}"
        return Response(Status.REDIRECT_TEMPORARY, jump_url)
    else:
        return Response(Status.INPUT, "Jump to page")


@app.route("/backlinks")
def backlinks(request):
    if request.query:
        url = unquote(request.query)
        if not url.startswith("gemini://"):
            url = "gemini://{}".format(url)
        internal_backlinks, external_backlinks = gus.get_backlinks(url)
        body = render_template(
            "backlinks.gmi",
            url=url,
            internal_backlinks=internal_backlinks,
            external_backlinks=external_backlinks,
            index_modification_time=gus.statistics["index_modification_time"]
        )
        return Response(Status.SUCCESS, "text/gemini", body)
    else:
        return Response(Status.INPUT, "Gemini URL")