html_generator.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. '''
  2. This is a library for formatting GPT-4chan and chat 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 generate_basic_html(s):
  18. s = '\n'.join([f'<p>{line}</p>' for line in s.split('\n')])
  19. s = f'<style>{readable_css}</style><div class="container">{s}</div>'
  20. return s
  21. def process_post(post, c):
  22. t = post.split('\n')
  23. number = t[0].split(' ')[1]
  24. if len(t) > 1:
  25. src = '\n'.join(t[1:])
  26. else:
  27. src = ''
  28. src = re.sub('>', '&gt;', src)
  29. src = re.sub('(&gt;&gt;[0-9]*)', '<span class="quote">\\1</span>', src)
  30. src = re.sub('\n', '<br>\n', src)
  31. src = f'<blockquote class="message">{src}\n'
  32. src = f'<span class="name">Anonymous </span> <span class="number">No.{number}</span>\n{src}'
  33. return src
  34. def generate_4chan_html(f):
  35. posts = []
  36. post = ''
  37. c = -2
  38. for line in f.splitlines():
  39. line += "\n"
  40. if line == '-----\n':
  41. continue
  42. elif line.startswith('--- '):
  43. c += 1
  44. if post != '':
  45. src = process_post(post, c)
  46. posts.append(src)
  47. post = line
  48. else:
  49. post += line
  50. if post != '':
  51. src = process_post(post, c)
  52. posts.append(src)
  53. for i in range(len(posts)):
  54. if i == 0:
  55. posts[i] = f'<div class="op">{posts[i]}</div>\n'
  56. else:
  57. posts[i] = f'<div class="reply">{posts[i]}</div>\n'
  58. output = ''
  59. output += f'<style>{_4chan_css}</style><div id="parent"><div id="container">'
  60. for post in posts:
  61. output += post
  62. output += '</div></div>'
  63. output = output.split('\n')
  64. for i in range(len(output)):
  65. output[i] = re.sub(r'^(&gt;(.*?)(<br>|</div>))', r'<span class="greentext">\1</span>', output[i])
  66. output[i] = re.sub(r'^<blockquote class="message">(&gt;(.*?)(<br>|</div>))', r'<blockquote class="message"><span class="greentext">\1</span>', output[i])
  67. output = '\n'.join(output)
  68. return output
  69. def get_image_cache(path):
  70. cache_folder = Path("cache")
  71. if not cache_folder.exists():
  72. cache_folder.mkdir()
  73. mtime = os.stat(path).st_mtime
  74. if (path in image_cache and mtime != image_cache[path][0]) or (path not in image_cache):
  75. img = Image.open(path)
  76. img.thumbnail((200, 200))
  77. output_file = Path(f'cache/{path.name}_cache.png')
  78. img.convert('RGB').save(output_file, format='PNG')
  79. image_cache[path] = [mtime, output_file.as_posix()]
  80. return image_cache[path][1]
  81. def load_html_image(paths):
  82. for str_path in paths:
  83. path = Path(str_path)
  84. if path.exists():
  85. return f'<img src="file/{get_image_cache(path)}">'
  86. return ''
  87. def generate_chat_html(history, name1, name2, character):
  88. output = f'<style>{cai_css}</style><div class="chat" id="chat">'
  89. img_bot = load_html_image([f"characters/{character}.{ext}" for ext in ['png', 'jpg', 'jpeg']] + ["img_bot.png","img_bot.jpg","img_bot.jpeg"])
  90. img_me = load_html_image(["img_me.png", "img_me.jpg", "img_me.jpeg"])
  91. for i,_row in enumerate(history[::-1]):
  92. row = [markdown.markdown(re.sub(r"(.)```", r"\1\n```", entry), extensions=['fenced_code']) for entry in _row]
  93. output += f"""
  94. <div class="message">
  95. <div class="circle-bot">
  96. {img_bot}
  97. </div>
  98. <div class="text">
  99. <div class="username">
  100. {name2}
  101. </div>
  102. <div class="message-body">
  103. {row[1]}
  104. </div>
  105. </div>
  106. </div>
  107. """
  108. if not (i == len(history)-1 and len(row[0]) == 0):
  109. output += f"""
  110. <div class="message">
  111. <div class="circle-you">
  112. {img_me}
  113. </div>
  114. <div class="text">
  115. <div class="username">
  116. {name1}
  117. </div>
  118. <div class="message-body">
  119. {row[0]}
  120. </div>
  121. </div>
  122. </div>
  123. """
  124. output += "</div>"
  125. return output