messages.py 5.7 KB

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