diff options
Diffstat (limited to 'talermerchantdemos')
-rw-r--r-- | talermerchantdemos/blog/articles/scrap1_11.html | 1 | ||||
-rw-r--r-- | talermerchantdemos/blog/blog.py | 48 | ||||
-rw-r--r-- | talermerchantdemos/blog/content.py | 13 | ||||
-rw-r--r-- | talermerchantdemos/blog/templates/article_frame.html | 5 | ||||
-rw-r--r-- | talermerchantdemos/blog/templates/confirm_refund.html | 4 | ||||
-rw-r--r-- | talermerchantdemos/blog/templates/index.html | 7 |
6 files changed, 47 insertions, 31 deletions
diff --git a/talermerchantdemos/blog/articles/scrap1_11.html b/talermerchantdemos/blog/articles/scrap1_11.html index 71c693b..17471df 100644 --- a/talermerchantdemos/blog/articles/scrap1_11.html +++ b/talermerchantdemos/blog/articles/scrap1_11.html @@ -52,4 +52,3 @@ traditional style, please visit <br/> </p> <img alt="song-book-jutta-scrunch-crop" src="/essay/11._The_Free_Software_Song/data/song-book-jutta-scrunch-crop.jpg"/> - diff --git a/talermerchantdemos/blog/blog.py b/talermerchantdemos/blog/blog.py index c54a8d6..37d7c20 100644 --- a/talermerchantdemos/blog/blog.py +++ b/talermerchantdemos/blog/blog.py @@ -94,18 +94,29 @@ def internal_error(e): ## -# Serve the main index page. +# Serve the main index page, redirecting to /<lang>/ # # @return response object of the index page. @app.route("/") def index(): + supported = ['en', 'de' ] + default = 'en' + target = flask.request.accept_languages.best_match(supported, default) + return flask.redirect("/" + target + "/", code=302) + +## +# Serve the main index page for a particular language. +# +# @return response object of the index page. +@app.route("/<lang>/") +def start(lang): return flask.render_template( - "templates/index.html", merchant_currency=CURRENCY, articles=ARTICLES.values() + "templates/index.html", lang=lang, merchant_currency=CURRENCY, articles=ARTICLES.values() ) -@app.route("/confirm-refund/<order_id>", methods=["GET"]) -def confirm_refund(order_id): +@app.route("/<lang>/confirm-refund/<order_id>", methods=["GET"]) +def confirm_refund(lang, order_id): session_id = flask.session.get("session_id", "") pay_status = backend_get( BACKEND_URL, f"private/orders/{order_id}", params=dict(session_id=session_id) @@ -113,7 +124,7 @@ def confirm_refund(order_id): order_status = pay_status.get("order_status") if order_status != "paid": err_abort( - 400, message="can't refund unpaid article", + 400, message="Cannot refund unpaid article", ) article_name = pay_status["contract_terms"]["extra"]["article_name"] return flask.render_template( @@ -127,16 +138,15 @@ def confirm_refund(order_id): # # @param order_id the order ID of the transaction to refund. # @return the following errors (named by HTTP response code): -# - 400: no article was asked to be refunded! -# - 401: the refund was asked on a non-payed article. -# - 500: the backend was unable to give response. -# Or, in the successful case, a redirection to the -# "refund URL" is returned; then the wallet will run -# the refund protocol in a transparent way. +# - 400: order unknown +# - 402: the refund was asked on an unpaid article. +# - 302: in the successful case, a redirection to the +# "refund URL" is returned; then the wallet will run +# the refund protocol in a transparent way. @app.route("/refund/<order_id>", methods=["POST"]) -def refund(order_id): +def refund(lang, order_id): if not order_id: - return flask.jsonify(dict(error="Aborting refund: article not payed")), 401 + return flask.jsonify(dict(error="Aborting refund: order unknown")), 400 session_id = flask.session.get("session_id", "") pay_status = backend_get( BACKEND_URL, f"private/orders/{order_id}", params=dict(session_id=session_id) @@ -204,9 +214,10 @@ def render_article(article_name, data, order_id): # In the successful case, either the article is returned, or # the browser gets redirected to a page where the wallet can # send the payment. -@app.route("/essay/<article_name>") +@app.route("/<lang>/essay/<article_name>") +@app.route("/<lang>/essay/<article_name>/data/<data>") @app.route("/essay/<article_name>/data/<data>") -def article(article_name, data=None): +def article(article_name, lang=None, data=None): # We use an explicit session ID so that each payment (or payment replay) is # bound to a browser. This forces re-play and prevents sharing the article # by just sharing the URL. @@ -218,9 +229,11 @@ def article(article_name, data=None): ## # First-timer; generate order first. if not order_id: + if not lang: + err_abort(403, message="Direct access forbidden") order = dict( amount=ARTICLE_AMOUNT, - extra=dict(article_name=article_name), + extra=dict(article_name=article_name,lang=lang), fulfillment_url=flask.request.base_url, summary="Essay: " + article_name.replace("_", " "), # 10 minutes time for a refund @@ -251,5 +264,6 @@ def article(article_name, data=None): # Redirect the browser to a page where the wallet can # run the payment protocol. response = flask.redirect(pay_status["order_status_url"]) - response.set_cookie("order_id", order_id, path=f"/essay/{article_name}") + response.set_cookie("order_id", order_id, path=urllib.parse.quote(f"/essay/{article_name}")) + response.set_cookie("order_id", order_id, path=urllib.parse.quote(f"/{lang}/essay/{article_name}")) return response diff --git a/talermerchantdemos/blog/content.py b/talermerchantdemos/blog/content.py index a0e90dd..fa9ace2 100644 --- a/talermerchantdemos/blog/content.py +++ b/talermerchantdemos/blog/content.py @@ -26,7 +26,7 @@ from pkg_resources import resource_stream, resource_filename LOGGER = logging.getLogger(__name__) NOISY_LOGGER = logging.getLogger("chardet.charsetprober") NOISY_LOGGER.setLevel(logging.INFO) -Article = namedtuple("Article", "slug title teaser main_file extra_files") +Article = namedtuple("Article", "slug title teaser main_file extra_files lang") ## # @var if a article is added to this list, then it will @@ -43,8 +43,9 @@ ARTICLES = OrderedDict() # @param main_file path to the article's HTML file. # @param extra_file collection of extra files associated with the # article, like images and sounds. -def add_article(slug, title, teaser, main_file, extra_files): - ARTICLES[slug] = Article(slug, title, teaser, main_file, extra_files) +# @param lang language of the arcile +def add_article(slug, title, teaser, main_file, extra_files, lang='en'): + ARTICLES[slug] = Article(slug, title, teaser, main_file, extra_files, lang) ## @@ -85,7 +86,7 @@ def add_from_html(resource_name, teaser_paragraph=0, title=None): if title is None: title_el = soup.find("h1", attrs={"class": ["chapter", "unnumbered"]}) if title_el is None: - LOGGER.warning("Can't extract title from '%s'", resource_name) + LOGGER.warning("Cannot extract title from '%s'", resource_name) title = resource_name else: title = title_el.get_text().strip() @@ -97,7 +98,7 @@ def add_from_html(resource_name, teaser_paragraph=0, title=None): teaser = paragraphs[teaser_paragraph].get_text() else: teaser = teaser.get_text() - re_proc = re.compile("^/essay/[^/]+/data/[^/]+$") + re_proc = re.compile("^/[^/][^/]/essay/[^/]+/data/[^/]+$") imgs = soup.find_all("img") extra_files = [] for img in imgs: @@ -114,7 +115,7 @@ def add_from_html(resource_name, teaser_paragraph=0, title=None): else: LOGGER.warning("Image src and slug don't match: '%s' != '%s'" \ % (img['src'].split(os.sep)[2], slug)) - add_article(slug, title, teaser, resource_name, extra_files) + add_article(slug, title, teaser, resource_name, extra_files, 'en') add_from_html("blog/articles/scrap1_U.0.html", 0) diff --git a/talermerchantdemos/blog/templates/article_frame.html b/talermerchantdemos/blog/templates/article_frame.html index 1efc0d1..8c2b6d4 100644 --- a/talermerchantdemos/blog/templates/article_frame.html +++ b/talermerchantdemos/blog/templates/article_frame.html @@ -4,7 +4,8 @@ <hr> <p> - You don't like this article? <a href="{{ url_for('confirm_refund', order_id=order_id) }}">Get a refund</a> within - the first hour after buying it. + You did not like this article? + <a href="{{ url_for('confirm_refund', lang='en', order_id=order_id) }}">Get a refund</a> + within the first hour after buying it. </p> {% endblock main %} diff --git a/talermerchantdemos/blog/templates/confirm_refund.html b/talermerchantdemos/blog/templates/confirm_refund.html index 10aaa74..c4773d3 100644 --- a/talermerchantdemos/blog/templates/confirm_refund.html +++ b/talermerchantdemos/blog/templates/confirm_refund.html @@ -3,12 +3,12 @@ <h1>Refund Article?</h1> <p> - Do you want to get a refund for the article <em>{{ article_name }}</em>? After you've requested a refund, + Do you want to get a refund for the article <em>{{ article_name }}</em>? After you have requested a refund, you won't be able to read the article anymore. </p> <p> - You will only be able to receive the refund on the same wallet that you've used to pay + You will only be able to receive the refund on the same wallet that you have used to pay for this article originally. </p> diff --git a/talermerchantdemos/blog/templates/index.html b/talermerchantdemos/blog/templates/index.html index 0159779..0702bf7 100644 --- a/talermerchantdemos/blog/templates/index.html +++ b/talermerchantdemos/blog/templates/index.html @@ -24,14 +24,15 @@ <h2>Chapters</h2> <div> Click on an individual chapter to to purchase it. You can - get free, virtual money to buy articles on this page at the <a href="{{ env('TALER_ENV_URL_BANK', '#') }}">bank</a>. + get free, virtual money to buy articles on this page at the + <a href="{{ env('TALER_ENV_URL_BANK', '#') }}">bank</a>. </div> <div> {% for article in articles %} <div class="notice"> - <h3><a href="{{ url_for('article', article_name=article.slug) }}">{{article.title}}</a></h3> - <p>{{ article.teaser|safe }} <a href="{{ url_for('article', article_name=article.slug) }}">(Pay to read more...)</a></p> + <h3><a href="{{ url_for('article', lang=article.lang, article_name=article.slug) }}">{{article.title}}</a></h3> + <p>{{ article.teaser|safe }} <a href="{{ url_for('article', lang=article.lang, article_name=article.slug) }}">(Pay to read more...)</a></p> </div> {% else %} <em>(No articles available)</em> |