indexer.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import os
  2. import itertools
  3. from groupie import models
  4. from groupie.utils import json
  5. def get_ids(dir):
  6. if not os.path.exists(dir): return []
  7. def sort_key(filename):
  8. return map(int, filename.split('_'))
  9. files = []
  10. for filename in os.listdir(dir):
  11. if filename.startswith('.'): continue
  12. files.append(filename)
  13. files.sort(key=sort_key)
  14. return files
  15. def get_post_ids(group):
  16. return get_ids(group.get_path('posts'))
  17. def get_posts_by_ids(group, ids):
  18. for post_id in ids:
  19. with open(group.get_path('posts', post_id)) as fp:
  20. post = models.Post(json.load(fp))
  21. post.group = group
  22. yield post
  23. def get_post_comments(group, post):
  24. for comment_id in get_ids(group.get_path('comments', post.id)):
  25. with open(group.get_path('comments', post.id, comment_id)) as fp:
  26. comment = models.Comment(json.load(fp))
  27. comment.post = post
  28. yield comment
  29. BODY_KEYS = ('message', 'name', 'caption', 'description')
  30. COMMENT_POP_WEIGHT = 2
  31. def popularity_func(obj):
  32. if isinstance(obj, models.Comment):
  33. obj = obj.post
  34. return obj.like_count + obj.comment_count * COMMENT_POP_WEIGHT
  35. def search(group, q, sort, page, limit):
  36. g = search_gen(group, q, sort)
  37. if sort == 'popular':
  38. g = sorted(g, key=popularity_func, reverse=True)
  39. start = (page - 1) * limit
  40. end = start + limit + 1
  41. result = list(itertools.islice(g, start, end))
  42. if len(result) > limit:
  43. result = result[:limit]
  44. next_page = page + 1
  45. else:
  46. next_page = None
  47. return result, next_page
  48. def search_gen(group, q, sort):
  49. q = q.lower()
  50. post_ids = get_post_ids(group)
  51. if sort == 'new':
  52. post_ids = reversed(post_ids)
  53. for post in get_posts_by_ids(group, post_ids):
  54. found = False
  55. for key in BODY_KEYS:
  56. value = post.data.get(key)
  57. if value:
  58. if q in value.lower():
  59. yield post
  60. found = True
  61. break
  62. if not found:
  63. for comment in get_post_comments(group, post):
  64. if q in comment.message.lower():
  65. yield comment
  66. break