浏览代码

Handle reply post request

Mohidul Islam 5 年之前
父节点
当前提交
8dded92b20
共有 6 个文件被更改,包括 86 次插入44 次删除
  1. 8 6
      dashboard/views.py
  2. 12 0
      gauth/auth_utils.py
  3. 19 2
      nlu_job/nlu_utils.py
  4. 1 18
      nlu_job/views.py
  5. 12 4
      review/background_job.py
  6. 34 14
      review/review_utils.py

+ 8 - 6
dashboard/views.py

@@ -5,7 +5,7 @@ from django.views.generic import View
 from review.models import Review, Reply
 from review.forms import ReplyForm
 from gauth.models import Location
-from review.review_utils import sync_all_review
+from review.review_utils import sync_all_review, reply_review
 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
 
 
@@ -55,11 +55,13 @@ class UnRepliedReviewList(View):
         review = Review.objects.filter(pk=review_id).first()
         now = timezone.now()
         if review:
-            review_reply = Reply(replied_text=reply, create_time=now)
-            review_reply.save()
-            review.reply = review_reply
-            review.save()
-            messages.success(request, f'Your reply has been posted!')
+            response = reply_review(review=review, replied_text=reply)
+            if response.status_code == 200:
+                review_reply = Reply(replied_text=reply, create_time=now)
+                review_reply.save()
+                review.reply = review_reply
+                review.save()
+                messages.success(request, f'Your reply has been posted!')
         return redirect('un-replied-review')
 
     def get(self, request, *args, **kwargs):

+ 12 - 0
gauth/auth_utils.py

@@ -5,6 +5,18 @@ from django.conf import settings
 from .models import UserModel
 from requests import get
 
+ACCESS_TOKEN_URI = settings.HOST_URI + '/token'
+
+
+def get_auth_header():
+    # Make a header with access key for making request in google-my-business server.
+    access_token = get(ACCESS_TOKEN_URI).text
+    headers = {
+        'authorization': 'Bearer ' + access_token,
+        'content-type': 'application/json'
+    }
+    return headers
+
 
 def has_expired(credentials):
     expiry_time = credentials['expiry']

+ 19 - 2
nlu_job/nlu_utils.py

@@ -1,10 +1,27 @@
 from django.conf import settings
 from requests import post
 import json
+from difflib import SequenceMatcher
+from review.models import Review
 
 nlu_server_url = settings.NLU_SERVER_URI
 
 
+def filter_with_last_ten_reviews(location_id, replies):
+    replies = list(replies)
+    revs = Review.objects.filter(location_id=location_id).exclude(reply=None).order_by('-update_time')[:12]
+    for r in revs:
+        s1 = r.reply.replied_text
+        for rep in replies:
+            s2 = rep.reply
+            similarity = SequenceMatcher(None, s1, s2).ratio()
+            if similarity > 0.7:
+                replies.remove(rep)
+                print(similarity, '--------------', rep.reply_category)
+
+    return replies
+
+
 def model_inference(text):
     url = nlu_server_url + '/model/parse'
     payload = {'text': text}
@@ -19,7 +36,7 @@ def model_inference(text):
 def is_a_name(name):
     '''
     function that decide whether it is a person name or not
-    :param -> a string usually reviewer name:
+    :param : name -> a string usually reviewer name
     :return -> a boolean True/False:
     '''
 
@@ -40,7 +57,7 @@ def analyze_inference(response):
     ['intent', 'entities', 'intent_ranking', 'text']
     we took all intents that has more than 10% of intent confident.
     all the intents that has bellow confidence has been omitted.
-    :param response:
+    :param response: a json response that RASA NLU server respond.
     :return: dictionary with key of intent and value of it's confident.
     '''
 

+ 1 - 18
nlu_job/views.py

@@ -4,24 +4,7 @@ from django.shortcuts import redirect
 from review.forms import ReplyForm
 from review.models import Review, CustomReply
 
-from difflib import SequenceMatcher
-
-from .nlu_utils import model_inference, analyze_inference
-
-
-def filter_with_last_ten_reviews(location_id, replies):
-    replies = list(replies)
-    revs = Review.objects.filter(location_id=location_id).exclude(reply=None).order_by('-update_time')[:12]
-    for r in revs:
-        s1 = r.reply.replied_text
-        for rep in replies:
-            s2 = rep.reply
-            similarity = SequenceMatcher(None, s1, s2).ratio()
-            if similarity > 0.7:
-                replies.remove(rep)
-                print(similarity, '--------------', rep.reply_category)
-
-    return replies
+from .nlu_utils import model_inference, analyze_inference, filter_with_last_ten_reviews
 
 
 def predict_report(request, review_id):

+ 12 - 4
review/background_job.py

@@ -1,9 +1,10 @@
+import random
 from threading import Thread
 from time import sleep
 from django.utils import timezone
-from random import choice
 from .models import Review, CustomReply
 from nlu_job.nlu_utils import is_a_name
+from review.review_utils import reply_review
 
 
 def un_replied_reviews_with_no_comment():
@@ -15,10 +16,10 @@ def un_replied_reviews_with_no_comment():
 
 def generate_reply(review):
     replies = CustomReply.objects.filter(reply_category='no_comment')
-    reply = choice(replies)
+    reply = random.choice(replies)
     name = review.reviewer_name
     if is_a_name(name):
-        parsable_name = ', '+name.title()
+        parsable_name = ', '+name.split()[0].capitalize()
     else:
         parsable_name = ''
     replied_text = reply.reply %parsable_name
@@ -29,7 +30,14 @@ def task():
     while True:
         reviews = un_replied_reviews_with_no_comment()
         # TODO: reply reviews in background
-        sleep(60*60*6)
+        for review in reviews:
+            replied_text = generate_reply(review)
+            response = reply_review(review=review, replied_text=replied_text)
+
+            if response.status_code == 200:
+                print(f'Reply for {review.reviewer_name}\'s comment in {review.location} has successfully done!')
+
+        sleep(60*random.randint(2, 5))
 
 
 thread = Thread(target=task)

+ 34 - 14
review/review_utils.py

@@ -1,6 +1,6 @@
-from requests import get
-from django.conf import settings
-from gauth.auth_utils import get_gmb_id
+import json
+from requests import get, put
+from gauth.auth_utils import get_gmb_id, get_auth_header
 from gauth.location_utils import get_all_location_ids
 from django.db.models import Max
 from .models import Review, Reply
@@ -9,8 +9,6 @@ from gauth.models import Location
 from django.utils import timezone
 
 
-ACCESS_TOKEN_URI = settings.HOST_URI + '/token'
-
 STAR_REVIEW_NUM = {'STAR_RATING_UNSPECIFIED': 0, 'ONE': 1, 'TWO': 2, 'THREE': 3, 'FOUR': 4, 'FIVE': 5}
 USER, GMB_ID = get_gmb_id()
 
@@ -20,22 +18,37 @@ def get_review_list_url(loc_id, next_page_token=''):
     return 'https://mybusiness.googleapis.com/v4/accounts/' + GMB_ID + '/locations/' + loc_id + '/reviews?pageToken='+next_page_token
 
 
+def get_reply_url(location_id, review_id):
+    _, account_id = get_gmb_id()
+    return f'https://mybusiness.googleapis.com/v4/accounts/{account_id}/locations/{location_id}/reviews/{review_id}/reply'
+
+
+def reply_review(review, replied_text):
+    '''
+    reply a review with a put request.
+    :param review: review object -> a review which you want to reply.
+    :param replied_text: string -> The actual reply that you want to post.
+    :return:
+    '''
+    url = get_reply_url(review.location.location_id, review.review_id)
+    headers = get_auth_header()
+    payload = json.dumps({'comment': replied_text})
+    response = put(url, headers=headers, data=payload)
+    return response
+
+
 def get_max_date(loc_id):
+    '''
+    find the maximum date of any particular location. the latest date
+    :param loc_id: Integer -> Globally unique ID for google my business locations.
+    :return: DateTime Obj -> The latest reviews date of that location.
+    '''
     # Function that takes a location id and return the latest updated review.
     largest = Review.objects.filter(location_id=loc_id).aggregate(Max('create_time'))['create_time__max']
     max_date = largest if largest else '1970-01-11 17:41:17.532740'
     return max_date
 
 
-def get_auth_header():
-    access_token = get(ACCESS_TOKEN_URI).text
-    headers = {
-        'authorization': 'Bearer ' + access_token,
-        'content-type': 'application/json'
-    }
-    return headers
-
-
 def filter_unrecorded_review_by_date(reviews, max_date):
     # A function that return only those reviews whose has larger value than
     # the max create_time value in review database.
@@ -47,6 +60,12 @@ def filter_unrecorded_review_by_date(reviews, max_date):
 
 
 def insert_review_into_database(unrecorded_reviews, loc):
+    '''
+    Insert reviews to database.
+    :param unrecorded_reviews: all reviews for location.
+    :param loc: location that unrecorded_reviews belongs to.
+    :return: It insert all reviews if it is not exits in database and return nothing.
+    '''
     for review in unrecorded_reviews:
         review_id = review.get('reviewId')
         # Check the review already in database then We don't need to store again.
@@ -61,6 +80,7 @@ def insert_review_into_database(unrecorded_reviews, loc):
         reviewer_name = reviewer.get('displayName')
         reviewer_photo = reviewer.get('profilePhotoUrl')
         review_reply = review.get('reviewReply')
+        # Check if it is already  replied.
         if review_reply:
             replied_text = review_reply.get('comment')
             create_time = review_reply.get('updateTime')