html_generator.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. '''
  2. This is a library for formatting text outputs as nice HTML.
  3. '''
  4. import os
  5. import re
  6. from pathlib import Path
  7. import markdown
  8. from PIL import Image
  9. # This is to store the paths to the thumbnails of the profile pictures
  10. image_cache = {}
  11. with open(Path(__file__).resolve().parent / '../css/html_readable_style.css', 'r') as f:
  12. readable_css = f.read()
  13. with open(Path(__file__).resolve().parent / '../css/html_4chan_style.css', 'r') as css_f:
  14. _4chan_css = css_f.read()
  15. with open(Path(__file__).resolve().parent / '../css/html_cai_style.css', 'r') as f:
  16. cai_css = f.read()
  17. def fix_newlines(string):
  18. string = string.replace('\n', '\n\n')
  19. string = re.sub(r"\n{3,}", "\n\n", string)
  20. string = string.strip()
  21. return string
  22. # This could probably be generalized and improved
  23. def convert_to_markdown(string):
  24. string = string.replace('\\begin{code}', '```')
  25. string = string.replace('\\end{code}', '```')
  26. string = string.replace('\\begin{blockquote}', '> ')
  27. string = string.replace('\\end{blockquote}', '')
  28. string = re.sub(r"(.)```", r"\1\n```", string)
  29. # string = fix_newlines(string)
  30. return markdown.markdown(string, extensions=['fenced_code'])
  31. def generate_basic_html(string):
  32. string = convert_to_markdown(string)
  33. string = f'<style>{readable_css}</style><div class="container">{string}</div>'
  34. return string
  35. def process_post(post, c):
  36. t = post.split('\n')
  37. number = t[0].split(' ')[1]
  38. if len(t) > 1:
  39. src = '\n'.join(t[1:])
  40. else:
  41. src = ''
  42. src = re.sub('>', '&gt;', src)
  43. src = re.sub('(&gt;&gt;[0-9]*)', '<span class="quote">\\1</span>', src)
  44. src = re.sub('\n', '<br>\n', src)
  45. src = f'<blockquote class="message">{src}\n'
  46. src = f'<span class="name">Anonymous </span> <span class="number">No.{number}</span>\n{src}'
  47. return src
  48. def generate_4chan_html(f):
  49. posts = []
  50. post = ''
  51. c = -2
  52. for line in f.splitlines():
  53. line += "\n"
  54. if line == '-----\n':
  55. continue
  56. elif line.startswith('--- '):
  57. c += 1
  58. if post != '':
  59. src = process_post(post, c)
  60. posts.append(src)
  61. post = line
  62. else:
  63. post += line
  64. if post != '':
  65. src = process_post(post, c)
  66. posts.append(src)
  67. for i in range(len(posts)):
  68. if i == 0:
  69. posts[i] = f'<div class="op">{posts[i]}</div>\n'
  70. else:
  71. posts[i] = f'<div class="reply">{posts[i]}</div>\n'
  72. output = ''
  73. output += f'<style>{_4chan_css}</style><div id="parent"><div id="container">'
  74. for post in posts:
  75. output += post
  76. output += '</div></div>'
  77. output = output.split('\n')
  78. for i in range(len(output)):
  79. output[i] = re.sub(r'^(&gt;(.*?)(<br>|</div>))', r'<span class="greentext">\1</span>', output[i])
  80. output[i] = re.sub(r'^<blockquote class="message">(&gt;(.*?)(<br>|</div>))', r'<blockquote class="message"><span class="greentext">\1</span>', output[i])
  81. output = '\n'.join(output)
  82. return output
  83. def get_image_cache(path):
  84. cache_folder = Path("cache")
  85. if not cache_folder.exists():
  86. cache_folder.mkdir()
  87. mtime = os.stat(path).st_mtime
  88. if (path in image_cache and mtime != image_cache[path][0]) or (path not in image_cache):
  89. img = Image.open(path)
  90. img.thumbnail((200, 200))
  91. output_file = Path(f'cache/{path.name}_cache.png')
  92. img.convert('RGB').save(output_file, format='PNG')
  93. image_cache[path] = [mtime, output_file.as_posix()]
  94. return image_cache[path][1]
  95. def load_html_image(paths):
  96. for str_path in paths:
  97. path = Path(str_path)
  98. if path.exists():
  99. return f'<img src="file/{get_image_cache(path)}">'
  100. return ''
  101. def generate_chat_html(history, name1, name2, character):
  102. output = f'<style>{cai_css}</style><div class="chat" id="chat">'
  103. img_bot = load_html_image([f"characters/{character}.{ext}" for ext in ['png', 'jpg', 'jpeg']] + ["img_bot.png","img_bot.jpg","img_bot.jpeg"])
  104. img_me = load_html_image(["img_me.png", "img_me.jpg", "img_me.jpeg"])
  105. for i,_row in enumerate(history[::-1]):
  106. row = [convert_to_markdown(entry) for entry in _row]
  107. output += f"""
  108. <div class="message">
  109. <div class="circle-bot">
  110. {img_bot}
  111. </div>
  112. <div class="text">
  113. <div class="username">
  114. {name2}
  115. </div>
  116. <div class="message-body">
  117. {row[1]}
  118. </div>
  119. </div>
  120. </div>
  121. """
  122. if not row[0]: # don't display empty user messages
  123. continue
  124. output += f"""
  125. <div class="message">
  126. <div class="circle-you">
  127. {img_me}
  128. </div>
  129. <div class="text">
  130. <div class="username">
  131. {name1}
  132. </div>
  133. <div class="message-body">
  134. {row[0]}
  135. </div>
  136. </div>
  137. </div>
  138. """
  139. output += "</div>"
  140. return output