taiseipage.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #!/usr/bin/env python3
  2. from flask import (
  3. Flask,
  4. Response,
  5. redirect,
  6. render_template,
  7. request,
  8. url_for,
  9. )
  10. from markupsafe import Markup
  11. from urllib.parse import (
  12. urljoin,
  13. )
  14. from feedgen.feed import (
  15. FeedGenerator,
  16. )
  17. import datetime
  18. import markdown
  19. import os
  20. app = Flask(__name__)
  21. app.jinja_env.trim_blocks = True
  22. app.jinja_env.lstrip_blocks = True
  23. news_dir = 'news'
  24. screens_dir = 'static/screenshots'
  25. def load_news_file(filename):
  26. f = open(os.path.join(news_dir, filename), 'r')
  27. date = f.readline().strip('\n')
  28. title = f.readline().strip('\n')
  29. content = f.read()
  30. content = Markup(markdown.markdown(content))
  31. f.close()
  32. return (date, title, content, filename)
  33. def load_news():
  34. news = []
  35. l = os.listdir(news_dir)
  36. for fn in l:
  37. news.append(load_news_file(fn))
  38. news.sort(key=lambda x: x[0])
  39. news.reverse()
  40. return news
  41. def load_screendirs():
  42. dirs = []
  43. for fn in os.listdir(screens_dir):
  44. if fn == 'thumb':
  45. continue
  46. num, caption = fn.split("_")
  47. screens = os.listdir(os.path.join(screens_dir, fn))
  48. dirs.append((int(num), caption, fn, screens))
  49. dirs.sort(key=lambda x: x[0])
  50. dirs.reverse()
  51. return dirs
  52. def make_external(url):
  53. return urljoin(request.url_root, url)
  54. def render_template_page(page, *args, **kwargs):
  55. return render_template(page + '.html', *args, page=page, **kwargs)
  56. @app.route('/')
  57. def index():
  58. return render_template_page('home')
  59. @app.route('/news')
  60. def news():
  61. return render_template_page('news', news=load_news())
  62. @app.route('/news.atom')
  63. def newsfeed():
  64. def makedate(strdate):
  65. dt = datetime.datetime.strptime(strdate, '%Y-%m-%d %H:%M')
  66. return datetime.datetime(
  67. year=dt.year,
  68. month=dt.month,
  69. day=dt.day,
  70. hour=dt.hour,
  71. minute=dt.minute,
  72. tzinfo=datetime.timezone.utc,
  73. )
  74. news = load_news()
  75. feed = FeedGenerator()
  76. feed.icon(make_external('static/favicon.ico'))
  77. feed.id(request.url)
  78. feed.language('en-US')
  79. feed.link(href=make_external('news'))
  80. feed.link(href=request.url, rel='self')
  81. feed.title('The State of Taisei')
  82. feed.updated(makedate(news[0][0]))
  83. for article in news:
  84. date = makedate(article[0])
  85. url = make_external("/news/" + article[3])
  86. entry = feed.add_entry()
  87. entry.author(name='Taisei team')
  88. entry.content(article[2], type='html')
  89. entry.id(url)
  90. entry.link(href=make_external("/news/" + article[3]))
  91. entry.published(date)
  92. entry.title(article[1])
  93. entry.updated(date)
  94. return Response(feed.atom_str(), mimetype='text/xml')
  95. @app.route('/news/<filename>')
  96. def news_entry(filename):
  97. news = load_news_file(filename)
  98. return render_template_page('news_entry', content=news)
  99. @app.route('/media')
  100. def media():
  101. dirs = load_screendirs()
  102. return render_template_page('media', dirs=dirs)
  103. @app.route('/download')
  104. def download(filename=None):
  105. return render_template_page('download')
  106. @app.route('/play')
  107. def play():
  108. return redirect("https://play.taisei-project.org/", code=301)
  109. @app.route('/discord')
  110. def discord():
  111. return redirect("https://discord.gg/JEHCMzW", code=302)
  112. @app.route('/code')
  113. def code():
  114. return redirect("https://github.com/taisei-project/taisei", code=301)
  115. @app.route('/license')
  116. def license():
  117. return render_template_page('license')
  118. @app.template_filter('indent')
  119. def indent_filter(s, width, *args):
  120. # incomplete reimplementation of the default 'indent' filter
  121. # because apparently it doesn't work with 'safe' correctly
  122. first, *rest = s.split('\n')
  123. return ('\n').join([first] + [' ' * width + s for s in rest])
  124. if __name__ == "__main__":
  125. app.debug = True
  126. app.run()