Youtube API commentThreads.update возвращает ошибку 400 при ответе на topLevelComment

Сообщение о возможной ошибке в Youtube Api commentThreads.update

Название затронутого API: CommentThreads: update

Краткое описание проблемы: CommentThreads: обновление При вызове этого API для обновления topLevelComment, возвращаемого CommentThreads.list, я получил ошибку 400. Я использовал этот API во внутреннем инструменте, чтобы отвечать на комментарии. Он работал нормально в течение последних месяцев... и в последние дни (~ 2016-11-07) без каких-либо изменений кода на моей стороне API начал возвращать ошибку 400. У меня сейчас все мои внутренние системы комментариев остановлены, так как я не мог понять, как это исправить. Все, что я пробовал и тестировал, приводило меня к ошибке 400 и сообщению ниже.

«Хотя это может быть временной ошибкой, обычно это указывает на то, что ввод запроса недействителен».

Даже используя консоль API, я получил ту же ошибку! Моя ставка? Это временная ошибка, которую, я надеюсь, Google сможет исправить.

Шаги для воспроизведения проблемы:

  1. Получить потоки «holdForReview», используя CommentThreads.list
  2. Попробуйте обновить возвращенный topLevelComment, изменив ["topLevelComment"]["snippet"]["textOriginal"] = "некоторый текст". При желании измените «статус модерации» на «опубликовано». Ошибка такая же.
  3. Такое поведение можно легко обнаружить с помощью примеров Python API, в частности файла comment_threads.py из https://github.com/youtube/api-samples/blob/master/python/comment_threads.py

Ожидаемый результат: комментарий верхнего уровня из Thread должен стать видимым (после того, как модерацияСтатус будет опубликована) и иметь «какой-то текст» в качестве первого дочернего комментария в качестве ответа.

Фактические результаты:

    {
 "error": {
  "errors": [
   {
    "domain": "youtube.commentThread",
    "reason": "processingFailure",
    "message": "The API server failed to successfully process the request. While this can be a transient error, it usually indicates that the requests input is invalid. Check the structure of the \u003ccode\u003ecommentThread\u003c/code\u003e resource in the request body to ensure that it is valid.",
    "locationType": "other",
    "location": "body"
   }
  ],
  "code": 400,
  "message": "The API server failed to successfully process the request. While this can be a transient error, it usually indicates that the requests input is invalid. Check the structure of the \u003ccode\u003ecommentThread\u003c/code\u003e resource in the request body to ensure that it is valid."
 }
}

Notes: I am providing a sample code below.

#!/usr/bin/python
# Usage example:
# python comment_threads.py --channelid='<channel_id>' --videoid='<video_id>' --text='<text>'
import httplib2
import os
import sys

from apiclient.discovery import build_from_document
from apiclient.errors import HttpError
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import argparser, run_flow

# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains

# the OAuth 2.0 information for this application, including its client_id and
# client_secret. You can acquire an OAuth 2.0 client ID and client secret from
# the {{ Google Cloud Console }} at
# {{ https://cloud.google.com/console }}.
# Please ensure that you have enabled the YouTube Data API for your project.
# For more information about using OAuth2 to access the YouTube Data API, see:
#   https://developers.google.com/youtube/v3/guides/authentication
# For more information about the client_secrets.json file format, see:
#   https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
CLIENT_SECRETS_FILE = "client_secrets.json"

# This OAuth 2.0 access scope allows for full read/write access to the
# authenticated user's account and requires requests to use an SSL connection.
YOUTUBE_READ_WRITE_SSL_SCOPE = "https://www.googleapis.com/auth/youtube.force-ssl"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"

# This variable defines a message to display if the CLIENT_SECRETS_FILE is
# missing.
MISSING_CLIENT_SECRETS_MESSAGE = """
WARNING: Please configure OAuth 2.0

To make this sample run you will need to populate the client_secrets.json file
found at:
   %s
with information from the APIs Console
https://console.developers.google.com

For more information about the client_secrets.json file format, please visit:
https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
""" % os.path.abspath(os.path.join(os.path.dirname(__file__),CLIENT_SECRETS_FILE))

# Authorize the request and store authorization credentials.
def get_authenticated_service(args):
  flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE, scope=YOUTUBE_READ_WRITE_SSL_SCOPE,message=MISSING_CLIENT_SECRETS_MESSAGE)

  storage = Storage("%s-oauth2.json" % sys.argv[0])
  credentials = storage.get()

  if credentials is None or credentials.invalid:
    credentials = run_flow(flow, storage, args)

  # Trusted testers can download this discovery document from the developers page
  # and it should be in the same directory with the code.
  with open("youtube-v3-discoverydocument.json", "r") as f:
    doc = f.read()
    return build_from_document(doc, http=credentials.authorize(httplib2.Http()))


# Call the API's commentThreads.list method to list the existing comments.
def get_comments(youtube, video_id, channel_id):
  results = youtube.commentThreads().list(
    part="snippet",
    videoId=video_id,
    channelId=channel_id,
    # ONLY FILTER COMMENTS THAT ARE HELD FOR REVIEW
    # THOSE COMMENTS ONLY HAVE ONE TOP LEVEL COMMENT
    moderationStatus="heldForReview",
    textFormat="plainText").execute()

  for item in results["items"]:
    comment = item["snippet"]["topLevelComment"]
    author = comment["snippet"]["authorDisplayName"]
    text = comment["snippet"]["textDisplay"]
    print "Comment by %s: %s" % (author, text)

  return results["items"]


# Call the API's commentThreads.insert method to insert a comment.
def insert_comment(youtube, channel_id, video_id, text):
  insert_result = youtube.commentThreads().insert(
    part="snippet",
    body=dict(
      snippet=dict(
        channelId=channel_id,
        videoId=video_id,
        topLevelComment=dict(
          snippet=dict(
            textOriginal=text
          )
        )
      )
    )
  ).execute()

  comment = insert_result["snippet"]["topLevelComment"]
  author = comment["snippet"]["authorDisplayName"]
  text = comment["snippet"]["textDisplay"]
  print "Inserted comment for %s: %s" % (author, text)


# Call the API's commentThreads.update method to update an existing comment.
def update_comment(youtube, comment):
  comment["snippet"]["topLevelComment"]["snippet"]["textOriginal"] = 'updated'
  update_result = youtube.commentThreads().update(
    part="snippet",    
    body=comment
  ).execute()

  comment = update_result["snippet"]["topLevelComment"]
  author = comment["snippet"]["authorDisplayName"]
  text = comment["snippet"]["textDisplay"]
  print "Updated comment for %s: %s" % (author, text)


if __name__ == "__main__":
  # The "channelid" option specifies the YouTube channel ID that uniquely
  # identifies the channel for which the comment will be inserted.
  argparser.add_argument("--channelid",
    help="Required; ID for channel for which the comment will be inserted.")
  # The "videoid" option specifies the YouTube video ID that uniquely
  # identifies the video for which the comment will be inserted.
  argparser.add_argument("--videoid",
    help="Required; ID for video for which the comment will be inserted.")
  # The "text" option specifies the text that will be used as comment.
  argparser.add_argument("--text", help="Required; text that will be used as comment.")
  args = argparser.parse_args()

  if not args.channelid:
    exit("Please specify channelid using the --channelid= parameter.")
  if not args.videoid:
    exit("Please specify videoid using the --videoid= parameter.")
  if not args.text:
    exit("Please specify text using the --text= parameter.")

  youtube = get_authenticated_service(args)
  try:
    # All the available methods are used in sequence just for the sake of an example.
    # Insert channel comment by omitting videoId
    # REMOVED AS IT IS NOT RELEVANT TO THE ERRRO REPORT. insert_comment(youtube, args.channelid, None, args.text)
    # Insert video comment
    # REMOVED AS IT IS NOT RELEVANT TO THE ERRRO REPORT. insert_comment(youtube, args.channelid, args.videoid, args.text)
    video_comments = get_comments(youtube, args.videoid, None)
    if video_comments:
      update_comment(youtube, video_comments[0])

  except HttpError, e:
    print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)
  else:
    print "Inserted, listed and updated top-level comments."

Of course, you will need your authorization files inside the same directory.


person Alex Benfica    schedule 09.11.2016    source источник
comment
Есть вопрос как часть этого вопроса. или вы просто делитесь проблемой, которую вы создали?   -  person DaImTo    schedule 09.11.2016
comment
Привет ДамлТо. Оба. Вопрос в следующем: есть ли другой способ ответить на комментарии верхнего уровня, не используя именно этот API?   -  person Alex Benfica    schedule 09.11.2016
comment
В этом случае, чтобы мы могли помочь вам в отладке вашего кода, вам необходимо опубликовать свой код. Нам не нужно видеть ваш запрос о проблеме. Ссылка на него, если вам нравится stackoverflow.com/help/mcve   -  person DaImTo    schedule 09.11.2016
comment
Единственный способ программно обновить потоки комментариев YouTube — developers.google.com/youtube/ v3/docs/commentThreads/update   -  person DaImTo    schedule 09.11.2016
comment
Я думал, что поделиться URL-адресом с github было бы идеально. Код представляет собой этот файл: github.com/ alexbenfica/commentThreads.update-bug-report/blob/ Именно так, как есть. Это пример вызова, который вызывает ошибку: python comment_threads.py --channelid=UCQzm6RcaOty8QU2VhHbRg-g --videoid=1AV4nTfIrts --text=Test Вы должны использовать канал, на который у вас есть права, и видео должно иметь комментарии со статусом модерации, удерживаемымForReview .   -  person Alex Benfica    schedule 09.11.2016
comment
ссылки умирают со временем, лучше всего включить код в свой вопрос, пожалуйста, прочитайте stackoverflow.com/help/how-to-ask и я бы тоже не стал загружать MCVE на ваш github.   -  person DaImTo    schedule 09.11.2016
comment
Ok. Ты прав. Должен ли я удалить этот вопрос и создать новый?   -  person Alex Benfica    schedule 09.11.2016
comment
или просто отредактируйте это нормально.   -  person DaImTo    schedule 09.11.2016
comment
Хорошо, убедитесь, что вы уполномочены сделать этот звонок. В документации указано, что параметр moderationStatus может использоваться только в правильно авторизованном запросе. Установите этот параметр, чтобы ограничить возвращаемые цепочки комментариев определенным состоянием модерации. Попробуйте использовать свой собственный видеоидентификатор здесь в разделе попробуйте part и проверьте, появляется ли по-прежнему код ошибки 400.   -  person KENdi    schedule 10.11.2016
comment
Я использую свой собственный канал, собственное видео и авторизованный запрос. Этот же скрипт работал нормально, так как он был создан в прошлом году или больше, и просто перестал работать несколько дней назад. Ошибка также возникает при использовании проводника API. Вы пробовали?   -  person Alex Benfica    schedule 10.11.2016
comment
Похоже, это действительно проблема API, так как я не могу отвечать или модерировать комментарии с помощью Hootsuite! Уже сообщил им! Любые идеи о том, как я могу исправить это?   -  person Alex Benfica    schedule 10.11.2016
comment
Это происходит прямо сейчас для меня с JS-скриптом, который до сих пор работал нормально. Даже на странице API простой запрос commentThread выдает эту ошибку: Developers.google.com/youtube/v3/docs/commentThreads/list#usage Думаю, проблема в this can be a transient error   -  person brasofilo    schedule 27.06.2018
comment
Да, определенно временная ошибка, мой скрипт снова работает   -  person brasofilo    schedule 27.06.2018