2
0

smiley.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #!/usr/bin/env python3
  2. # -*- coding: UTF-8 -*-
  3. import os
  4. import functools
  5. import re
  6. import json
  7. import struct
  8. from .common.textutil import get_file_b64
  9. STATIC_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static')
  10. TENCENT_SMILEY_FILE = os.path.join(STATIC_PATH, 'tencent-smiley.json')
  11. try:
  12. UNICODE_SMILEY_RE = re.compile(
  13. u'[\U00010000-\U0010ffff]|[\u2600-\u2764]|\u2122|\u00a9|\u00ae|[\ue000-\ue5ff]'
  14. )
  15. except re.error:
  16. # UCS-2 build
  17. UNICODE_SMILEY_RE = re.compile(
  18. u'[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u2600-\u2764]|\u2122|\u00a9|\u00ae|[\ue000-\ue5ff]'
  19. )
  20. HEAD = """.smiley {
  21. padding: 1px;
  22. background-position: -1px -1px;
  23. background-repeat: no-repeat;
  24. width: 20px;
  25. height: 20px;
  26. display: inline-block;
  27. vertical-align: top;
  28. zoom: 1;
  29. }
  30. """
  31. TEMPLATE = """.{name} {{
  32. background-image: url("data:image/png;base64,{b64}");
  33. background-size: 24px 24px;
  34. }}"""
  35. def _css_class_name(s):
  36. s = s.replace("/", "_")
  37. s = s.replace(".", "_")
  38. return "smiley_" + s
  39. class SmileyProvider(object):
  40. def __init__(self, html_replace=True):
  41. """ html_replace: replace smileycode by html.
  42. otherwise, replace by plain text
  43. """
  44. self.html_replace = html_replace
  45. if not html_replace:
  46. raise NotImplementedError()
  47. # [微笑] -> smiley/0.png
  48. self.tencent_smiley = json.load(open(TENCENT_SMILEY_FILE))
  49. self.used_smileys = set()
  50. def reset(self):
  51. self.used_smileys.clear()
  52. def gen_replace_elem(self, smiley_path):
  53. self.used_smileys.add(str(smiley_path))
  54. return '<span class="smiley {}"></span>'.format(_css_class_name(smiley_path))
  55. def replace_smileycode(self, msg):
  56. """ replace the smiley code in msg
  57. return a html
  58. """
  59. # pre-filter:
  60. if ('[' not in msg) and ('/' not in msg) and not UNICODE_SMILEY_RE.findall(msg):
  61. return msg
  62. for k, v in self.tencent_smiley.items():
  63. if k in msg:
  64. msg = msg.replace(k, self.gen_replace_elem(v))
  65. return msg
  66. return msg
  67. def gen_used_smiley_css(self):
  68. ret = HEAD
  69. for path in self.used_smileys:
  70. fname = os.path.join(STATIC_PATH, path)
  71. b64 = get_file_b64(fname)
  72. ret = ret + TEMPLATE.format(name=_css_class_name(path), b64=b64)
  73. return ret
  74. if __name__ == '__main__':
  75. smiley = SmileyProvider()
  76. msg = u"[挥手]哈哈呵呵hihi\U0001f684\u2728\u0001 /::<\ue415"
  77. msg = smiley.replace_smileycode(msg)
  78. smiley.gen_used_smiley_css()