Example #1
0
def create_app(testing=False):
    app = FlaskBase(
        __name__,
        "jaas.ai",
        template_folder="../templates",
        static_folder="../static",
    )

    app.testing = testing
    app.after_request(add_headers)
    app.before_request(prepare_redirects())
    app.before_request(prepare_deleted())

    blog_views = BlogViews(
        api=BlogAPI(
            session=session,
            thumbnail_width=354,
            thumbnail_height=180,
        ),
        blog_title="JAAS Case Studies",
        tag_ids=[3513],
        feed_description="Case Studies from happy JAAS users",
    )
    app.register_blueprint(build_blueprint(blog_views),
                           url_prefix="/case-studies")

    talisker.requests.configure(cs.session)

    init_handler(app)
    init_blueprint(app)
    init_dashboard(app)

    @app.template_filter("pluralize")
    def pluralize_filter(count):
        if int(count) > 1:
            return "s"
        else:
            return ""

    @app.context_processor
    def inject_utilities():
        return {
            "current_url_with_query": current_url_with_query,
            "external_urls": external_urls,
            "static_url": static_url,
        }

    @app.context_processor
    def inject_today_date():
        return {"current_year": datetime.date.today().year}

    app.jinja_env.add_extension("jinja2.ext.do")

    @app.context_processor
    def utility_processor():
        return {"image": image_template}

    return app
    def setUp(self):
        super().setUp()

        app = flask.Flask("main",
                          template_folder=f"{this_dir}/fixtures/templates")
        Reggie().init_app(app)

        blog = build_blueprint(blog_views=BlogViews(
            blog_title="Snapcraft Blog",
            blog_path="/",
            api=BlogAPI(session=requests.Session()),
        ))
        app.register_blueprint(blog, url_prefix="/")

        app.testing = True

        self.test_client = app.test_client()
Example #3
0
app.add_url_rule("/takeovers", view_func=takeovers_index)
engage_pages.init_app(app)

app.add_url_rule(
    "/engage/<page>/thank-you",
    view_func=engage_thank_you(engage_pages),
)

template_finder_view = TemplateFinder.as_view("template_finder")
session = talisker.requests.get_session()
app.add_url_rule("/", view_func=template_finder_view)
app.add_url_rule("/<path:subpath>", view_func=template_finder_view)

blog_views = BlogViews(
    api=BlogAPI(session=session, thumbnail_width=354, thumbnail_height=199),
    tag_ids=[3265],
    blog_title="博客",
    per_page=11,
)
app.register_blueprint(build_blueprint(blog_views), url_prefix="/blog")

# read releases.yaml
with open("releases.yaml") as releases:
    releases = yaml.load(releases, Loader=yaml.FullLoader)


# Template context
@app.context_processor
def context():
    return {"releases": releases}

Example #4
0
    return (
        flask.render_template(
            "advantage/index.html",
            openid=openid,
            accounts=accounts,
            enterprise_contracts=enterprise_contracts,
            personal_account=personal_account,
        ),
        headers,
    )


# Blog
# ===

blog_views = BlogViews(excluded_tags=[3184, 3265, 3408], per_page=11)
blog_blueprint = build_blueprint(blog_views)


def blog_custom_topic(slug):
    page_param = flask.request.args.get("page", default=1, type=int)
    context = blog_views.get_topic(slug, page_param)

    return flask.render_template(f"blog/topics/{slug}.html", **context)


def blog_custom_group(slug):
    page_param = flask.request.args.get("page", default=1, type=int)
    category_param = flask.request.args.get("category", default="", type=str)
    context = blog_views.get_group(slug, page_param, category_param)
Example #5
0
def init_blog(app, url_prefix):
    session = talisker.requests.get_session()
    blog_api = BlogAPI(
        session=session,
        thumbnail_width=354,
        thumbnail_height=199,
    )
    blog = build_blueprint(
        BlogViews(
            api=blog_api,
            blog_title="Juju Blog",
            tag_ids=[4059],
            excluded_tags=[3184, 3265, 3408],
        )
    )

    @blog.context_processor
    def add_newsletter():
        newsletter_subscribed = flask.request.args.get(
            "newsletter", default=False, type=bool
        )

        return {"newsletter_subscribed": newsletter_subscribed}

    @blog.route("/sitemap.xml")
    def sitemap():
        base_url = "https://juju.is/blog"
        links = []
        page = 1
        while True:
            url = (
                f"https://ubuntu.com/blog/wp-json/wp/v2/posts?"
                f"tags=4059&per_page=100&page={page}"
                f"&tags_exclude=3184%2C3265%2C3408"
            )

            response = session.get(url)
            if response.status_code == 400:
                break

            try:
                blog_response = response.json()
            except Exception:
                continue

            for post in blog_response:
                try:
                    date = (
                        parser.parse(post["date"])
                        .replace(tzinfo=None)
                        .strftime("%Y-%m-%d")
                    )
                    links.append(
                        {
                            "url": base_url + "/" + post["slug"],
                            "last_udpated": date,
                        }
                    )
                except Exception:
                    continue

            page = page + 1

        xml_sitemap = flask.render_template(
            "sitemap/sitemap.xml",
            base_url=base_url,
            links=links,
        )

        response = flask.make_response(xml_sitemap)
        response.headers["Content-Type"] = "application/xml"
        response.headers["Cache-Control"] = "public, max-age=43200"

        return response

    app.register_blueprint(blog, url_prefix=url_prefix)
Example #6
0
class RegexConverter(BaseConverter):
    def __init__(self, url_map, *items):
        super(RegexConverter, self).__init__(url_map)
        self.regex = items[0]


app = flask.Flask(__name__,
                  template_folder="../templates",
                  static_folder="../static")

app.before_request(prepare_redirects())

app.url_map.strict_slashes = False
app.url_map.converters["regex"] = RegexConverter

app.wsgi_app = ProxyFix(app.wsgi_app)
if app.debug:
    app.wsgi_app = DebuggedApplication(app.wsgi_app)

talisker.flask.register(app)
talisker.logs.set_global_extra({"service": "jp.ubuntu.com"})

set_handlers(app)
app.register_blueprint(jp_website)

blog_views = BlogViews(blog_title="Ubuntu blog", tag_ids=[3184])
app.register_blueprint(build_blueprint(blog_views), url_prefix="/blog")

if __name__ == "__main__":
    app.run(host="0.0.0.0")
Example #7
0
def init_blog(app, url_prefix):
    blog = build_blueprint(
        BlogViews(blog_title="Snapcraft Blog", tag_ids=[2996]))

    @blog.route("/api/snap-posts/<snap>")
    def snap_posts(snap):
        try:
            blog_tags = wordpress_api.get_tag_by_name(f"sc:snap:{snap}")
        except Exception:
            blog_tags = None

        blog_articles = None
        articles = []

        if blog_tags:
            try:
                blog_articles, total_pages = wordpress_api.get_articles(
                    blog_tags["id"], 3)
            except Exception:
                blog_articles = []

            for article in blog_articles:
                transformed_article = logic.transform_article(
                    article, featured_image=None, author=None)
                articles.append({
                    "slug":
                    transformed_article["slug"],
                    "title":
                    transformed_article["title"]["rendered"],
                })

        return flask.jsonify(articles)

    @blog.route("/api/series/<series>")
    def snap_series(series):
        blog_articles = None
        articles = []

        try:
            blog_articles, total_pages = wordpress_api.get_articles(series)
        except Exception:
            blog_articles = []

        for article in blog_articles:
            transformed_article = logic.transform_article(article,
                                                          featured_image=None,
                                                          author=None)
            articles.append({
                "slug": transformed_article["slug"],
                "title": transformed_article["title"]["rendered"],
            })

        return flask.jsonify(articles)

    @blog.context_processor
    def add_newsletter():
        newsletter_subscribed = flask.request.args.get("newsletter",
                                                       default=False,
                                                       type=bool)

        return {"newsletter_subscribed": newsletter_subscribed}

    app.register_blueprint(blog, url_prefix=url_prefix)
Example #8
0
app = FlaskBase(
    __name__,
    "kubeflow-news.com",
    template_folder="../templates",
    static_folder="../static",
    template_404="404.html",
    template_500="500.html",
)

session = talisker.requests.get_session()

# Blog
blog_views = BlogViews(
    api=BlogAPI(session=session,
                api_url="https://ubuntu.com/blog/wp-json/wp/v2"),
    blog_title="kubeflow-news",
    tag_ids=[3408],
    excluded_tags=[3184, 3265],
)

app.register_blueprint(build_blueprint(blog_views), url_prefix="/")


@app.template_filter("pluralize")
def pluralize_filter(total_posts):
    if int(total_posts) > 1:
        return "s"
    else:
        return ""

Example #9
0
    modify_query,
    month_name,
    months_list,
    navigation,
    releases,
)

app = FlaskBase(
    __name__,
    "ubuntu.com",
    template_folder="../templates",
    static_folder="../static",
)

# Blog
blog_views = BlogViews(excluded_tags=[3184, 3265, 3408])


@app.route("/blog/topics/<regex('maas|design|juju|robotics|snapcraft'):slug>")
def custom_topic(slug):
    page_param = flask.request.args.get("page", default=1, type=int)
    context = blog_views.get_topic(slug, page_param)

    return flask.render_template(f"blog/topics/{slug}.html", **context)


@app.route("/blog/<regex('cloud-and-server|desktop|internet-of-things'):slug>")
def custom_group(slug):
    page_param = flask.request.args.get("page", default=1, type=int)
    category_param = flask.request.args.get("category", default="", type=str)
    context = blog_views.get_group(slug, page_param, category_param)
Example #10
0
from canonicalwebteam.flask_base.app import FlaskBase

from webapp.blueprint import jp_website
import webapp.template_utils as template_utils

session = talisker.requests.get_session()
app = FlaskBase(
    __name__,
    "jp.ubuntu.com",
    template_folder="../templates",
    static_folder="../static",
)

app.register_blueprint(jp_website)
blog_views = BlogViews(
    api=Wordpress(session=session), blog_title="Ubuntu blog", tag_ids=[3184]
)
app.register_blueprint(build_blueprint(blog_views), url_prefix="/blog")

# read releases.yaml
with open("releases.yaml") as releases:
    releases = yaml.load(releases, Loader=yaml.FullLoader)


# Template context
@app.context_processor
def context():
    return {
        "format_date": template_utils.format_date,
        "get_json_feed": template_utils.get_json_feed_content,
        "replace_admin": template_utils.replace_admin,
Example #11
0
def create_app(testing=False):
    app = FlaskBase(
        __name__,
        "jaas.ai",
        template_folder="../templates",
        static_folder="../static",
    )

    app.testing = testing
    app.after_request(add_headers)
    app.before_request(prepare_redirects("redirects.yaml"))
    app.before_request(
        prepare_redirects("permanent-redirects.yaml", permanent=True))
    app.before_request(prepare_deleted())

    blog_views = BlogViews(
        api=BlogAPI(
            session=session,
            thumbnail_width=354,
            thumbnail_height=180,
        ),
        blog_title="JAAS Case Studies",
        tag_ids=[3513],
        feed_description="Case Studies from happy JAAS users",
    )
    app.register_blueprint(build_blueprint(blog_views),
                           url_prefix="/case-studies")

    # Handlers
    # ===
    @app.errorhandler(404)
    def page_not_found(error):
        """
        For 404 pages, display the 404.html template,
        passing through the error description.
        """

        return flask.render_template("404.html", error=error.description), 404

    @app.errorhandler(500)
    def internal_server_error(error):
        """
        For 500 pages, display the 500.html template,
        passing through the error.
        """

        return flask.render_template("500.html", error=error), 500

    @app.errorhandler(410)
    def gone(error):
        """
        For 410 pages, display the 410.html template,
        passing through the error.
        """

        return flask.render_template("410.html", error=error), 410

    # Blueprints
    # ===
    app.register_blueprint(jaasai)

    # Dashboard and redirect views
    # ===
    @app.route("/models")
    @app.route("/models/<path:path>")
    @app.route("/controllers")
    @app.route("/controllers/<path:path>")
    def dashboard_index(path=None):
        """
        Send /models and /controllers to the index page
        """

        return flask.render_template("dashboard/index.html")

    @app.route("/config.js")
    @app.route("/manifest.json")
    @app.route("/ghost-bundle.svg")
    def dashboard_files():
        """
        Load dashboard files directly
        """

        return flask.render_template("dashboard" + flask.request.path)

    @app.route("/q/")
    @app.route("/q/<path:path>")
    def search_redirect(path=None):
        """
        Handle redirects from jujucharms.com search URLS to the jaas.ai format.
        e.g. /q/k8s/demo?sort=-name&series=xenial will redirect to
        /search?q=k8s+demo&sort=-name&series=xenial
        """
        query_string = []
        if path:
            query_string.append("q={}".format(path.replace("/", "+")))
        if flask.request.query_string:
            query_string.append(str(flask.request.query_string, "utf-8"))
        return flask.redirect("/search?{}".format("&".join(query_string)),
                              code=302)

    @app.route("/<charm_or_bundle_name>")
    @app.route("/<charm_or_bundle_name>/<series_or_version>")
    @app.route("/<charm_or_bundle_name>/<series_or_version>/<version>")
    def details_redirect(
        charm_or_bundle_name,
        series_or_version=None,
        version=None,
    ):

        charmhub_url = "https://charmhub.io/" + charm_or_bundle_name
        return flask.redirect(charmhub_url, code=301)

    # Template filters
    # ===
    @app.template_filter("pluralize")
    def pluralize_filter(count):
        if int(count) > 1:
            return "s"
        else:
            return ""

    @app.context_processor
    def inject_utilities():
        return {
            "current_url_with_query": current_url_with_query,
            "external_urls": external_urls,
            "static_url": static_url,
        }

    @app.context_processor
    def inject_today_date():
        return {"current_year": datetime.date.today().year}

    app.jinja_env.add_extension("jinja2.ext.do")

    @app.context_processor
    def utility_processor():
        return {"image": image_template}

    return app
Example #12
0
from webapp.blueprint import jp_website
import webapp.template_utils as template_utils

session = talisker.requests.get_session()
app = FlaskBase(
    __name__,
    "jp.ubuntu.com",
    template_folder="../templates",
    static_folder="../static",
)

app.register_blueprint(jp_website)
blog_views = BlogViews(
    api=BlogAPI(session=session),
    blog_title="Ubuntu blog",
    tag_ids=[3184],
    per_page=11,
)
app.register_blueprint(build_blueprint(blog_views), url_prefix="/blog")

# read releases.yaml
with open("releases.yaml") as releases:
    releases = yaml.load(releases, Loader=yaml.FullLoader)


@app.errorhandler(404)
def not_found_error(error):
    return flask.render_template("404.html"), 404


@app.errorhandler(500)
Example #13
0
def init_blog(app, url_prefix):
    wordpress_api = Wordpress(session=talisker.requests.get_session())
    blog = build_blueprint(
        BlogViews(api=wordpress_api,
                  blog_title="Snapcraft Blog",
                  tag_ids=[2996]))

    @blog.route("/api/snap-posts/<snap>")
    def snap_posts(snap):
        try:
            blog_tags = wordpress_api.get_tag_by_name(f"sc:snap:{snap}")
        except NotFoundError:
            blog_tags = None

        blog_articles = None
        articles = []

        third_party_blogs = get_yaml("blog/content/blog-posts.yaml")

        if third_party_blogs and snap in third_party_blogs:
            post = third_party_blogs[snap]
            cdn_image = "/".join([
                "https://res.cloudinary.com",
                "canonical",
                "image",
                "fetch",
                "f_auto,q_auto,fl_sanitize,w_346,h_231,c_fill",
                post["image"],
            ])
            brand_image = "https://assets.ubuntu.com/v1/aae0f33a-omgubuntu.svg"
            image_element = "".join([
                f'<img src="{cdn_image}" ',
                'style="display:block">',
                f'<img src="{brand_image}" ',
                'class="p-blog-post__source" />',
            ])
            articles.append({
                "slug": post["uri"],
                "title": post["title"],
                "image": image_element,
            })

        if blog_tags:
            snapcraft_tag = wordpress_api.get_tag_by_name("snapcraft.io")

            try:
                blog_articles, total_pages = wordpress_api.get_articles(
                    blog_tags["id"], 3 - len(articles))
            except RequestException:
                blog_articles = []

            for article in blog_articles:
                transformed_article = helpers.transform_article(article)

                if transformed_article["image"]:
                    featured_media = image_template(
                        url=transformed_article["image"]["source_url"],
                        alt="",
                        width="346",
                        height="231",
                        fill=True,
                        hi_def=True,
                        loading="auto",
                    )
                else:
                    featured_media = None

                url = f"/blog/{transformed_article['slug']}"

                if snapcraft_tag["id"] not in transformed_article["tags"]:
                    url = f"https://ubuntu.com{url}"

                articles.append({
                    "slug":
                    url,
                    "title":
                    transformed_article["title"]["rendered"],
                    "image":
                    featured_media,
                })

        return flask.jsonify(articles)

    @blog.route("/api/series/<series>")
    def snap_series(series):
        blog_articles = None
        articles = []

        try:
            blog_articles, total_pages = wordpress_api.get_articles(series)
        except RequestException:
            blog_articles = []

        for article in blog_articles:
            transformed_article = helpers.transform_article(article)
            articles.append({
                "slug": transformed_article["slug"],
                "title": transformed_article["title"]["rendered"],
            })

        return flask.jsonify(articles)

    @blog.context_processor
    def add_newsletter():
        newsletter_subscribed = flask.request.args.get("newsletter",
                                                       default=False,
                                                       type=bool)

        return {"newsletter_subscribed": newsletter_subscribed}

    app.register_blueprint(blog, url_prefix=url_prefix)
Example #14
0
session = talisker.requests.get_session()
app = FlaskBase(
    __name__,
    "jp.ubuntu.com",
    template_folder="../templates",
    static_folder="../static",
    template_404="404.html",
    template_500="500.html",
)

blog_views = BlogViews(
    api=BlogAPI(
        session=session,
        api_url="https://ubuntu.com/blog/wp-json/wp/v2",
        thumbnail_width=354,
        thumbnail_height=180,
    ),
    blog_title="Ubuntu blog",
    tag_ids=[3184],
    per_page=11,
)
app.register_blueprint(build_blueprint(blog_views), url_prefix="/blog")

# Engage pages and takeovers from Discourse
# This section needs to provide takeover data for /
discourse_api = DiscourseAPI(
    base_url="https://discourse.ubuntu.com/",
    session=session,
)

engage_path = "/engage"
Example #15
0
    (
        "/appliance/<regex('[a-z-]+'):appliance>/"
        "<regex('(raspberry-pi2?|intel-nuc|vm)'):device>"
    ),
    view_func=appliance_install,
)
app.add_url_rule(
    "/appliance/portfolio",
    view_func=appliance_portfolio,
)

# blog section

blog_views = BlogViews(
    api=BlogAPI(session=session),
    excluded_tags=[3184, 3265, 3408, 3960],
    per_page=11,
)
app.add_url_rule(
    "/blog/topics/<regex('maas|design|juju|robotics|snapcraft'):slug>",
    view_func=BlogCustomTopic.as_view("blog_topic", blog_views=blog_views),
)
app.add_url_rule(
    "/blog/<regex('cloud-and-server|desktop|internet-of-things'):slug>",
    view_func=BlogCustomGroup.as_view("blog_group", blog_views=blog_views),
)
app.add_url_rule(
    "/blog/press-centre",
    view_func=BlogPressCentre.as_view("press_centre", blog_views=blog_views),
)
app.add_url_rule(
Example #16
0
    ),
    view_func=download_thank_you,
)
app.add_url_rule("/getubuntu/releasenotes", view_func=releasenotes_redirect)
app.add_url_rule(
    "/search", "search", build_search_view(template_path="search.html")
)
app.add_url_rule(
    "/appliance/<regex('.+'):app>/<regex('.+'):device>",
    view_func=appliance_install,
)
# blog section

blog_views = BlogViews(
    api=Wordpress(session=session),
    excluded_tags=[3184, 3265, 3408],
    per_page=11,
)
app.add_url_rule(
    "/blog/topics/<regex('maas|design|juju|robotics|snapcraft'):slug>",
    view_func=BlogCustomTopic.as_view("blog_topic", blog_views=blog_views),
)
app.add_url_rule(
    "/blog/<regex('cloud-and-server|desktop|internet-of-things'):slug>",
    view_func=BlogCustomGroup.as_view("blog_group", blog_views=blog_views),
)
app.add_url_rule(
    "/blog/press-centre",
    view_func=BlogPressCentre.as_view("press_centre", blog_views=blog_views),
)
app.register_blueprint(build_blueprint(blog_views), url_prefix="/blog")
Example #17
0
def init_blog(app, url_prefix):
    session = talisker.requests.get_session()
    blog_api = BlogAPI(
        session=session,
        thumbnail_width=354,
        thumbnail_height=199,
    )
    blog = build_blueprint(
        BlogViews(
            api=blog_api,
            blog_title="Snapcraft Blog",
            tag_ids=[2996],
            excluded_tags=[3184, 3265, 3408],
        )
    )

    @blog.route("/api/snap-posts/<snap>")
    def snap_posts(snap):
        try:
            blog_tags = blog_api.get_tag_by_slug(f"sc:snap:{snap}")
        except NotFoundError:
            blog_tags = None

        blog_articles = None
        articles = []

        if blog_tags:
            snapcraft_tag = blog_api.get_tag_by_slug("snapcraft.io")

            try:
                blog_articles, total_pages = blog_api.get_articles(
                    tags=blog_tags["id"],
                    tags_exclude=[3184, 3265, 3408],
                    per_page=3 - len(articles),
                )
            except RequestException:
                blog_articles = []

            for article in blog_articles:
                if article["image"]:
                    featured_media = image_template(
                        url=article["image"]["source_url"],
                        alt="",
                        width="346",
                        height="231",
                        fill=True,
                        hi_def=True,
                        loading="auto",
                    )
                else:
                    featured_media = None

                url = f"/blog/{article['slug']}"

                if snapcraft_tag["id"] not in article["tags"]:
                    url = f"https://ubuntu.com{url}"

                articles.append(
                    {
                        "slug": url,
                        "title": article["title"]["rendered"],
                        "image": featured_media,
                    }
                )

        return flask.jsonify(articles)

    @blog.route("/api/series/<series>")
    def snap_series(series):
        blog_articles = None
        articles = []

        try:
            blog_articles, total_pages = blog_api.get_articles(series)
        except RequestException:
            blog_articles = []

        for article in blog_articles:
            articles.append(
                {
                    "slug": article["slug"],
                    "title": article["title"]["rendered"],
                }
            )

        return flask.jsonify(articles)

    @blog.context_processor
    def add_newsletter():
        newsletter_subscribed = flask.request.args.get(
            "newsletter", default=False, type=bool
        )

        return {"newsletter_subscribed": newsletter_subscribed}

    @blog.route("/sitemap.xml")
    def sitemap():
        base_url = "https://snapcraft.io/blog"
        links = []
        page = 1
        while True:
            url = (
                f"https://ubuntu.com/blog/wp-json/wp/v2/posts?"
                f"tags=2996&per_page=100&page={page}"
                f"&tags_exclude=3184%2C3265%2C3408"
            )

            response = session.get(url)
            if response.status_code == 400:
                break

            try:
                blog_response = response.json()
            except Exception:
                continue

            for post in blog_response:
                try:
                    date = (
                        parser.parse(post["date"])
                        .replace(tzinfo=None)
                        .strftime("%Y-%m-%d")
                    )
                    links.append(
                        {
                            "url": base_url + "/" + post["slug"],
                            "last_udpated": date,
                        }
                    )
                except Exception:
                    continue

            page = page + 1

        xml_sitemap = flask.render_template(
            "sitemap/sitemap.xml",
            base_url=base_url,
            links=links,
        )

        response = flask.make_response(xml_sitemap)
        response.headers["Content-Type"] = "application/xml"
        response.headers["Cache-Control"] = "public, max-age=43200"

        return response

    app.register_blueprint(blog, url_prefix=url_prefix)
Example #18
0
from canonicalwebteam.blog import BlogViews
from canonicalwebteam.blog.flask import build_blueprint
from canonicalwebteam.flask_base.app import FlaskBase

app = FlaskBase(
    __name__,
    "kubeflow-news.com",
    template_folder="../templates",
    static_folder="../static",
    template_404="404.html",
    template_500="500.html",
)

# Blog
blog_views = BlogViews(blog_title="kubeflow-news",
                       tag_ids=[3408],
                       excluded_tags=[3184, 3265])

app.register_blueprint(build_blueprint(blog_views), url_prefix="/")


@app.template_filter("pluralize")
def pluralize_filter(total_posts):
    if int(total_posts) > 1:
        return "s"
    else:
        return ""


@app.template_filter("descending_years")
def descending_years_filter(end_year):
Example #19
0
    __name__,
    "cn.ubuntu.com",
    template_folder="../templates",
    static_folder="../static",
    template_404="404.html",
    template_500="500.html",
)

template_finder_view = TemplateFinder.as_view("template_finder")
session = talisker.requests.get_session()
app.add_url_rule("/", view_func=template_finder_view)
app.add_url_rule("/<path:subpath>", view_func=template_finder_view)

blog_views = BlogViews(
    api=Wordpress(session=session),
    tag_ids=[3265],
    blog_title="博客",
    per_page=11,
)
app.register_blueprint(build_blueprint(blog_views), url_prefix="/blog")

# read releases.yaml
with open("releases.yaml") as releases:
    releases = yaml.load(releases, Loader=yaml.FullLoader)


# Template context
@app.context_processor
def context():
    return {"releases": releases}