messages.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. from flask import Flask, render_template, make_response
  2. from flask_paginate import Pagination, get_page_parameter, get_page_args
  3. from flask_caching import Cache
  4. from flask import request
  5. import pendulum
  6. import subprocess
  7. import base64
  8. import os
  9. base_path = "/messagebase"
  10. app = Flask(__name__, static_url_path=base_path + "/static")
  11. @app.template_filter("datefmt")
  12. def format_datetime(value):
  13. dt = pendulum.from_timestamp(value, tz=pendulum.tz.local_timezone())
  14. return dt.to_datetime_string()
  15. # Check Configuring Flask-Caching section for more details
  16. # cache = Cache(app, config={"CACHE_TYPE": "filesystem", "CACHE_DIR": "cache"})
  17. cache = Cache(app, config={"CACHE_TYPE": "redis", "CACHE_REDIS_HOST": "redis"})
  18. # cache = Cache(app, config={"CACHE_TYPE": "redis", "CACHE_REDIS_HOST": "olympus"})
  19. import jammin
  20. bases = {
  21. "FSX_General": "msgs/fsx_gen",
  22. "FSX_BBS": "msgs/fsx_bbs",
  23. "FSX_BOT": "msgs/fsx_bot",
  24. "FSX_Magicka": "msgs/fsx_mag",
  25. "HappyNet": "msgs/hpy_gen",
  26. }
  27. # bases = {"FSX_BOT": "fsx_bot"}
  28. # @cache.memoize(timeout=5 * 60, key_prefix="messages")
  29. @cache.memoize(timeout=5 * 60)
  30. def get_messages(base):
  31. messages = jammin.get_messages(base)
  32. messages.reverse()
  33. return messages
  34. @cache.memoize(timeout=60)
  35. def get_message(base, msgno):
  36. message = jammin.read_message(base, msgno)
  37. return message
  38. @app.errorhandler(404)
  39. def not_found(e):
  40. return render_template("404.html")
  41. @app.route(base_path + "/list")
  42. def list_bases():
  43. return render_template(
  44. "list.html", bases=bases, base_path=base_path, title="Message Areas"
  45. )
  46. # return 'Here would be a listing of message bases'
  47. @app.route(base_path + "/messages/<area>")
  48. def display_messages(area):
  49. if area not in bases:
  50. return render_template(
  51. "missing-area.html", base_path=base_path, title="Missing Area"
  52. )
  53. # messages = jammin.get_messages(bases[area])
  54. messages = get_messages(bases[area])
  55. # messages.reverse() # cached.reverse()
  56. page = request.args.get(get_page_parameter(), type=int, default=1)
  57. # get_page_arg defaults to page 1, per_page of 10
  58. PER_PAGE = 50
  59. total = len(messages)
  60. pagination = Pagination(
  61. page=page,
  62. total=total,
  63. css_framework="foundation",
  64. record_name="messages",
  65. per_page=PER_PAGE,
  66. )
  67. page, per_page, offset = get_page_args()
  68. start = (page - 1) * PER_PAGE
  69. end = start + PER_PAGE
  70. # messages = messages[(page-1) * PER_PAGE:offset+PER_PAGE]
  71. messages = messages[start:end]
  72. return render_template(
  73. "messages.html",
  74. messages=messages,
  75. area=area,
  76. pagination=pagination,
  77. base_path=base_path,
  78. title="Messages for " + bases[area],
  79. )
  80. @cache.memoize(timeout=60)
  81. def ansi_to_png(raw_ansi_bytes, idx):
  82. pid = os.getppid()
  83. ansifile = "{0}-{1}.ans".format(idx, pid)
  84. pngfile = "{0}-{1}.png".format(idx, pid)
  85. with open(ansifile, "wb") as fp:
  86. fp.write(raw_ansi_bytes)
  87. subprocess.run(["./ansilove", "-d", "-o", pngfile, ansifile])
  88. with open(pngfile, "rb") as fp:
  89. png = fp.read()
  90. os.unlink(ansifile)
  91. os.unlink(pngfile)
  92. return png
  93. def ansi_to_png64(raw_ansi_bytes, idx):
  94. png = ansi_to_png(raw_ansi_bytes, idx)
  95. return base64.b64encode(png).decode("utf-8")
  96. @app.route(base_path + "/image/<area>/<int:msgno>.png")
  97. def display_ansi(area, msgno):
  98. if area not in bases:
  99. return "RATS", 404
  100. message = get_message(bases[area], msgno)
  101. if not message:
  102. return "RATS", 404
  103. if not "text" in message:
  104. return "RATS", 404
  105. png = ansi_to_png(message["bytes"].replace(b"\r", b"\n"), msgno)
  106. response = make_response(png)
  107. response.headers.set("Content-Type", "image/png")
  108. return response
  109. # <img alt="My Image" src="data:image/png;base64,
  110. @app.route(base_path + "/read/<area>/<int:msgno>")
  111. def display_message(area, msgno):
  112. if area not in bases:
  113. return render_template(
  114. "missing-area.html", base_path=base_path, title="Missing Area"
  115. )
  116. # message = jammin.read_message(bases[area], msgno)
  117. message = get_message(bases[area], msgno)
  118. if not message:
  119. return render_template(
  120. "missing-message.html",
  121. base_path=base_path,
  122. area=area,
  123. title="Missing Message",
  124. )
  125. if "text" in message:
  126. if "\x1b" in message["text"]:
  127. # Ok, the message contains ANSI CODES -- Convert
  128. message["png"] = True
  129. # message["png"] = ansi_to_png64(
  130. # message["bytes"].replace(b"\r", b"\n"), msgno
  131. # )
  132. else:
  133. message["text"] = message["text"].replace("\r", "\n") # <br >\n")
  134. return render_template(
  135. "message.html",
  136. message=message,
  137. area=area,
  138. msgnumber=msgno,
  139. base_path=base_path,
  140. title="Message {0}".format(msgno),
  141. )