filters.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # **************************************************************************
  4. # Copyright © 2016 jianglin
  5. # File Name: filters.py
  6. # Author: jianglin
  7. # Email: xiyang0807@gmail.com
  8. # Created: 2016-11-07 21:00:32 (CST)
  9. # Last Update:星期日 2016-12-18 18:6:38 (CST)
  10. # By:
  11. # Description:
  12. # **************************************************************************
  13. from datetime import datetime
  14. from maple.extension import redis_data, cache
  15. from maple.settings import setting
  16. from api.topic.models import Topic
  17. from api.reply.models import Reply
  18. from api.user.models import User
  19. from flask import Markup, g
  20. from misaka import Markdown, HtmlRenderer
  21. from pygments import highlight
  22. from pygments.formatters import HtmlFormatter
  23. from pygments.lexers import get_lexer_by_name
  24. from bleach import clean
  25. def safe_clean(text):
  26. tags = ['b', 'i', 'font', 'br', 'blockquote', 'div', 'h2', 'a']
  27. attrs = {'*': ['style', 'id', 'class'], 'font': ['color'], 'a': ['href']}
  28. styles = ['color']
  29. return Markup(clean(text, tags=tags, attributes=attrs, styles=styles))
  30. def markdown(text):
  31. renderer = HtmlRenderer()
  32. md = Markdown(renderer, extensions=('fenced-code', ))
  33. return Markup(md(text))
  34. def safe_markdown(text):
  35. renderer = HtmlRenderer()
  36. md = Markdown(renderer, extensions=('fenced-code', ))
  37. return Markup(safe_clean(md(text)))
  38. def timesince(dt, default="just now"):
  39. from flask_babelex import format_datetime
  40. now = datetime.utcnow()
  41. diff = now - dt
  42. if diff.days > 10:
  43. return format_datetime(dt, 'Y-M-d H:m')
  44. elif diff.days <= 10 and diff.days > 0:
  45. periods = ((diff.days, "day", "days"), )
  46. elif diff.days <= 0 and diff.seconds > 3600:
  47. periods = ((diff.seconds / 3600, "hour", "hours"), )
  48. elif diff.seconds <= 3600 and diff.seconds > 90:
  49. periods = ((diff.seconds / 60, "minute", "minutes"), )
  50. else:
  51. return default
  52. for period, singular, plural in periods:
  53. if period:
  54. return "%d %s ago" % (period, singular if period == 1 else plural)
  55. return default
  56. class Filters(object):
  57. def safe_markdown(text):
  58. class HighlighterRenderer(HtmlRenderer):
  59. def blockcode(self, text, lang):
  60. lang = 'python'
  61. if not lang:
  62. return '\n<pre><code>{}</code></pre>\n'.format(text.strip(
  63. ))
  64. lexer = get_lexer_by_name(lang, stripall=True)
  65. formatter = HtmlFormatter()
  66. return highlight(text, lexer, formatter)
  67. renderer = HighlighterRenderer()
  68. md = Markdown(renderer, extensions=('fenced-code', ))
  69. return Markup(md(safe_clean(text)))
  70. # return Markup(md(text))
  71. def timesince(dt, default="just now"):
  72. from flask_babelex import format_datetime
  73. now = datetime.utcnow()
  74. diff = now - dt
  75. if diff.days > 10:
  76. return format_datetime(dt, 'Y-M-d H:m')
  77. elif diff.days <= 10 and diff.days > 0:
  78. periods = ((diff.days, "day", "days"), )
  79. elif diff.days <= 0 and diff.seconds > 3600:
  80. periods = ((diff.seconds / 3600, "hour", "hours"), )
  81. elif diff.seconds <= 3600 and diff.seconds > 90:
  82. periods = ((diff.seconds / 60, "minute", "minutes"), )
  83. else:
  84. return default
  85. for period, singular, plural in periods:
  86. if period:
  87. return "%d %s ago" % (period, singular
  88. if period == 1 else plural)
  89. return default
  90. def show_time():
  91. from flask_babelex import format_datetime
  92. if g.user.is_authenticated:
  93. return 'LOCALE:' + format_datetime(datetime.utcnow())
  94. else:
  95. return 'UTC:' + format_datetime(datetime.utcnow())
  96. def get_user_infor(name):
  97. user = User.query.filter(User.username == name).first()
  98. return user
  99. @cache.memoize(timeout=60)
  100. def get_last_reply(uid):
  101. reply = Reply.query.join(Reply.topic).filter(Topic.id == uid).first()
  102. return reply
  103. @cache.memoize(timeout=30)
  104. def get_read_count(id):
  105. read = redis_data.hget('topic:%s' % str(id), 'read')
  106. replies = redis_data.hget('topic:%s' % str(id), 'replies')
  107. if not read:
  108. read = 0
  109. else:
  110. read = int(read)
  111. if not replies:
  112. replies = 0
  113. else:
  114. replies = int(replies)
  115. return replies, read
  116. @cache.memoize(timeout=30)
  117. def is_collected(topicId):
  118. from maple.topic.models import CollectTopic
  119. from flask_login import current_user
  120. for collect in current_user.collects:
  121. cid = CollectTopic.query.filter_by(
  122. collect_id=collect.id, topic_id=topicId).first()
  123. if cid is not None:
  124. return True
  125. return False
  126. def notice_count():
  127. from maple.forums.models import Notice
  128. if g.user.is_authenticated:
  129. count = Notice.query.filter_by(
  130. rece_id=g.user.id, is_read=False).count()
  131. if count > 0:
  132. return count
  133. return None
  134. @cache.memoize(timeout=60)
  135. def hot_tags():
  136. from api.tag.models import Tags
  137. tags = Tags.query.limit(9).all()
  138. return tags
  139. @cache.memoize(timeout=60)
  140. def recent_tags():
  141. from api.tag.models import Tags
  142. tags = Tags.query.limit(12).all()
  143. return tags
  144. def is_online(username):
  145. from maple.main.records import load_online_sign_users
  146. online_users = load_online_sign_users()
  147. if username in online_users:
  148. return True
  149. return False
  150. class Title(object):
  151. title = setting['title']
  152. picture = setting['picture']
  153. description = setting['description']
  154. def register_jinja2(app):
  155. app.jinja_env.globals['Title'] = Filters.Title
  156. app.jinja_env.globals['hot_tags'] = Filters.hot_tags
  157. app.jinja_env.globals['recent_tags'] = Filters.recent_tags
  158. app.jinja_env.globals['notice_count'] = Filters.notice_count
  159. app.jinja_env.globals['show_time'] = Filters.show_time
  160. app.jinja_env.filters['get_last_reply'] = Filters.get_last_reply
  161. app.jinja_env.filters['get_user_infor'] = Filters.get_user_infor
  162. app.jinja_env.filters['get_read_count'] = Filters.get_read_count
  163. app.jinja_env.filters['timesince'] = Filters.timesince
  164. app.jinja_env.filters['markdown'] = Filters.safe_markdown
  165. app.jinja_env.filters['safe_clean'] = safe_clean
  166. app.jinja_env.filters['is_collected'] = Filters.is_collected
  167. app.jinja_env.filters['is_online'] = Filters.is_online