review_utils.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. from requests import get
  2. from django.conf import settings
  3. from gauth.auth_utils import get_gmb_id
  4. from gauth.location_utils import get_all_location_ids
  5. from django.db.models import Max
  6. from .models import Review, Reply
  7. from gauth.models import Location
  8. from django.utils import timezone
  9. ACCESS_TOKEN_URI = settings.HOST_URI + '/token'
  10. STAR_REVIEW_NUM = {'STAR_RATING_UNSPECIFIED': 0, 'ONE': 1, 'TWO': 2, 'THREE': 3, 'FOUR': 4, 'FIVE': 5}
  11. USER, GMB_ID = get_gmb_id()
  12. def get_review_list_url(loc_id, next_page_token=''):
  13. # An helper function that make a url that need to consume GMB review api
  14. return 'https://mybusiness.googleapis.com/v4/accounts/' + GMB_ID + '/locations/' + loc_id + '/reviews?pageToken='+next_page_token
  15. def get_max_date(loc_id):
  16. # Function that takes a location id and return the latest updated review.
  17. largest = Review.objects.filter(location_id=loc_id).aggregate(Max('create_time'))['create_time__max']
  18. max_date = largest if largest else '1970-01-11 17:41:17.532740'
  19. return max_date
  20. def get_auth_header():
  21. access_token = get(ACCESS_TOKEN_URI).text
  22. headers = {
  23. 'authorization': 'Bearer ' + access_token,
  24. 'content-type': 'application/json'
  25. }
  26. return headers
  27. def filter_unrecorded_review_by_date(reviews, max_date):
  28. # A function that return only those reviews whose has larger value than
  29. # the max create_time value in review database.
  30. filtered_reviews = []
  31. for rev in reviews:
  32. if rev['createTime'] >= str(max_date):
  33. filtered_reviews.append(rev)
  34. return filtered_reviews
  35. def insert_review_into_database(unrecorded_reviews, loc):
  36. for review in unrecorded_reviews:
  37. review_id = review.get('reviewId')
  38. # Check the review already in database then We don't need to store again.
  39. rev = Review.objects.filter(pk=review_id).first()
  40. if rev:
  41. continue
  42. comment = review.get('comment')
  43. create_time = review.get('createTime')
  44. update_time = review.get('updateTime')
  45. star_rating = STAR_REVIEW_NUM[review.get('starRating')]
  46. reviewer = review.get('reviewer')
  47. reviewer_name = reviewer.get('displayName')
  48. reviewer_photo = reviewer.get('profilePhotoUrl')
  49. review_reply = review.get('reviewReply')
  50. if review_reply:
  51. replied_text = review_reply.get('comment')
  52. create_time = review_reply.get('updateTime')
  53. reply = Reply.objects.create(replied_text=replied_text, create_time=create_time)
  54. else:
  55. reply = None
  56. review = Review(
  57. review_id=review_id,
  58. comment=comment,
  59. create_time=create_time,
  60. update_time=update_time,
  61. star_rating=star_rating,
  62. reviewer_name=reviewer_name,
  63. reviewer_photo=reviewer_photo,
  64. location=loc,
  65. reply=reply
  66. )
  67. review.save()
  68. def sync_all_review(loc_id):
  69. '''
  70. Sync a location if any bad thing occur for example any network break.
  71. :param: loc_id -> Location id of a particular location
  72. :return: None -> It just update all reviews of this location and return nothing.
  73. '''
  74. loc = Location.objects.get(pk=loc_id)
  75. next_page_token = ''
  76. headers = get_auth_header()
  77. while True:
  78. url = get_review_list_url(loc_id, next_page_token)
  79. res = get(url, headers=headers)
  80. if res.status_code == 401:
  81. headers = get_auth_header()
  82. continue
  83. data = res.json()
  84. reviews = data['reviews']
  85. if len(reviews) != 0:
  86. insert_review_into_database(reviews, loc)
  87. next_page_token = data.get('nextPageToken')
  88. if next_page_token is None:
  89. break
  90. average_rating = data.get('averageRating')
  91. total_reviews = data.get('totalReviewCount')
  92. total_reviews_db = Review.objects.filter(location_id=loc_id).count()
  93. update_location_data(loc, average_rating, total_reviews, total_reviews_db)
  94. def update_location_data(loc, average_rating, total_reviews, total_reviews_db):
  95. loc.average_rating = average_rating
  96. loc.total_review = total_reviews
  97. loc.total_review_DB = total_reviews_db
  98. loc.save()
  99. def fetch_all_review(loc_id):
  100. loc = Location.objects.get(pk=loc_id)
  101. max_date = get_max_date(loc_id)
  102. headers = get_auth_header()
  103. url = get_review_list_url(loc_id)
  104. res = get(url, headers=headers)
  105. if res.status_code == 401:
  106. return
  107. data = res.json()
  108. reviews = data['reviews']
  109. average_rating = data.get('averageRating')
  110. total_reviews = data.get('totalReviewCount')
  111. unrecorded_reviews = filter_unrecorded_review_by_date(reviews, max_date)
  112. if len(unrecorded_reviews) != 0:
  113. insert_review_into_database(unrecorded_reviews, loc)
  114. total_reviews_db = Review.objects.filter(location_id=loc_id).count()
  115. update_location_data(loc, average_rating, total_reviews, total_reviews_db)
  116. def populate_reviews():
  117. start = timezone.now()
  118. locations = get_all_location_ids()
  119. for loc_id in locations:
  120. fetch_all_review(loc_id)
  121. end = timezone.now()
  122. elapsed = end - start
  123. print('-----------------------------------------------------------------------------------------')
  124. print(f'Elapsed time: {elapsed.seconds//60} minutes and {elapsed.seconds % 60} secs.')
  125. print('-----------------------------------------------------------------------------------------')