2016-08-12 1 views
2

Я пытался переделать подпись моих личных макросов на ZenDesk, и единственный способ сделать это через API. Так что я написал этот небольшой скрипт на Python, чтобы попытаться это сделать:Почему мои макросы ZenDesk обновляются, но никаких изменений на самом деле не происходит?

import sys 
import time 
import logging 
import requests 
import re 

start_time = time.time() 

# Set up logging 
logger = logging.getLogger() 
log_handler = logging.StreamHandler(sys.stdout) 
log_handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s - %(funcName)s - line %(lineno)d")) 
log_handler.setLevel(logging.DEBUG) 
logger.addHandler(log_handler) 
logger.setLevel(logging.DEBUG) 

def doTheGet(url, user, pwd): 
     response = requests.get(url, auth=(user + "/token", pwd)) 

     if response.status_code != 200: 
       logger.error("Status: %s (%s) Problem with the request. Exiting. %f seconds elapsed" % (response.status_code, response.reason, time.time() - start_time)) 
       exit() 

     data = response.json() 
     return data 

def doThePut(url, updated_data, user, pwd): 
     response = requests.put(url, json="{'macro': {'actions': %r}}" % updated_data, headers={"Content-Type": "application/json"}, auth=(user + "/token", pwd)) 

     if response.status_code != 200: 
       logger.error("Status: %s (%s) Problem with the request. Exiting. %f seconds elapsed" % (response.status_code, response.reason, time.time() - start_time)) 
       exit() 

     data = response.json() 
     return data 

def getMacros(): 
     macros = {} 

     data = doTheGet("https://mydomain.zendesk.com/api/v2/macros.json", "[email protected]", "111tokenZZZ") 

     def getMacros(macro_list, page, page_count): 
       if not page: 
         for macro in macro_list: 
           if macro["restriction"] and macro["active"]: 
             if macro["restriction"]["type"] == "User": 
               macros[macro["id"]] = macro["actions"] 
       else: 
         for macro in macro_list: 
           if macro["restriction"] and macro["active"]: 
             if macro["restriction"]["type"] == "User": 
               macros[macro["id"]] = macro["actions"] 

         page_count += 1 
         new_data = doTheGet(page, "[email protected]", "111tokenZZZ") 
         new_macs = new_data["macros"] 
         new_next_page = new_data["next_page"] 
         getMacros(new_macs, new_next_page, page_count) 


     macs = data["macros"] 
     current_page = 1 
     next_page = data["next_page"] 
     getMacros(macs, next_page, current_page) 
     return macros 

def updateMacros(): 
     macros = getMacros() 

     regular = "RegEx to match signature to be replaced$" #since some macros already have the updated signature 

     for macro in macros: 
       for action in macros[macro]: 
         if action["field"] == "comment_value": 
           if re.search(regular, action["value"][1]): 
             ind = action["value"][1].rfind("\n") 
             action["value"][1] = action["value"][1][:ind] + "\nNew signature" 

     return macros 

macs = updateMacros() 

for mac in macs: 
     doThePut("https://mydomain.zendesk.com/api/v2/macros/%d.json" % (mac), macs[mac], "[email protected]", "111tokenZZZ") 

Теперь работает все, как и ожидалось, и я не получаю никаких ошибок. Когда я перехожу к своим макросам в ZenDesk и сортирую их по последнему обновлению, я вижу, что скрипт что-то сделал, так как они показывают, что они обновлены сегодня. Однако на них ничего не меняется. Я убедился, что данные, которые я отправляю за , - (updateMacros- выполняет свою работу). Я убедился, что запросы отправляют ответ OK. Поэтому я отправляю обновленные данные, возвращая ответ 200, но the response sent back показывает мне макросы, как раньше, с нулевыми изменениями.

Единственное, что происходит со мной, возможно, в некотором роде неправильным - это формат данных, которые я отправляю, или что-то в этом роде. Но даже тогда я ожидал, что ответ не будет 200, затем ...

Что мне здесь не хватает?

ответ

4

Похоже, вы дважды кодирования данных JSON в запросе PUT:

response = requests.put(url, json="{'macro': {'actions': %r}}" % updated_data, headers={"Content-Type": "application/json"}, auth=(user + "/token", pwd)) 

Параметр JSON ожидает объект, который затем послушно кодирует в JSON и отправляет в теле запроса; это просто удобство; реализация просто,

if not data and json is not None: 
     # urllib3 requires a bytes-like body. Python 2's json.dumps 
     # provides this natively, but Python 3 gives a Unicode string. 
     content_type = 'application/json' 
     body = complexjson.dumps(json) 
     if not isinstance(body, bytes): 
      body = body.encode('utf-8') 

(источник: https://github.com/kennethreitz/requests/blob/master/requests/models.py#L424)

Поскольку значение всегда проходит через json.dumps(), если вы передаете строку, представляющую уже кодированный JSON он сам будет кодироваться:

"{\'macro\': {\'actions\': [{\'field\': \'comment_value\', \'value\': [\'channel:all\', \'Spiffy New Sig that will Never Be Saved\']}]}}" 

ZenDesk, получив JSON, он не ожидает, обновляет поле updated_at и ... ничего не делает. Вы можете проверить это, передав пустую строку - тот же результат.

Обратите внимание, что вы также полагаетесь на форматирование Python для заполнения своего JSON; это, вероятно, тоже плохая идея. Вместо этого давайте просто реконструировать наш макрос объект и пусть запросы кодировать его:

response = requests.put(url, json={'macro': {'actions': updated_data}}, headers={"Content-Type": "application/json"}, auth=(user + "/token", pwd)) 

Это должно делать то, что вы ожидаете.