การแจ้งเตือนสำหรับการเปลี่ยนแปลงทรัพยากร

เอกสารนี้อธิบายวิธีใช้การแจ้งเตือนแบบพุชที่แจ้งให้แอปพลิเคชันทราบเมื่อมีการเปลี่ยนแปลงทรัพยากร

ภาพรวม

Google ไดรฟ์ API มีการแจ้งเตือนแบบพุชที่ช่วยให้คุณตรวจสอบ การเปลี่ยนแปลงในทรัพยากรได้ คุณใช้ฟีเจอร์นี้เพื่อปรับปรุงประสิทธิภาพของ แอปพลิเคชันได้ ซึ่งช่วยให้คุณไม่ต้องเสียค่าใช้จ่ายเพิ่มเติมสำหรับเครือข่ายและการประมวลผล ที่เกี่ยวข้องกับการสำรวจทรัพยากรเพื่อดูว่ามีการเปลี่ยนแปลงหรือไม่ เมื่อใดก็ตามที่ทรัพยากรที่ดูมีการเปลี่ยนแปลง Google Drive API จะแจ้งให้แอปพลิเคชันของคุณทราบ

หากต้องการใช้ข้อความ Push คุณต้องทำ 2 สิ่งต่อไปนี้

  • ตั้งค่า URL ที่รับหรือเครื่องรับการเรียกกลับ "Webhook"

    ซึ่งเป็นเซิร์ฟเวอร์ HTTPS ที่จัดการข้อความการแจ้งเตือน API ที่ทริกเกอร์เมื่อทรัพยากรมีการเปลี่ยนแปลง

  • ตั้งค่า (Notification Channel) สำหรับปลายทางของทรัพยากรแต่ละรายการที่ต้องการ ดู

    ช่องจะระบุข้อมูลการกำหนดเส้นทางสำหรับการแจ้งเตือน ข้อความ คุณต้องระบุ URL ที่เฉพาะเจาะจงซึ่งต้องการรับการแจ้งเตือนเป็นส่วนหนึ่งของการตั้งค่าช่อง เมื่อใดก็ตามที่ทรัพยากรของช่องมีการเปลี่ยนแปลง Google Drive API จะส่งข้อความแจ้งเตือนเป็นPOST คำขอไปยัง URL นั้น

ปัจจุบัน Google ไดรฟ์ API รองรับการแจ้งเตือนการเปลี่ยนแปลงในเมธอด files และ changes

สร้างช่องทางการแจ้งเตือน

หากต้องการขอรับการแจ้งเตือนแบบพุช คุณต้องตั้งค่าแชแนลการแจ้งเตือน สำหรับแต่ละแหล่งข้อมูลที่ต้องการตรวจสอบ หลังจากตั้งค่าช่องทางการแจ้งเตือนแล้ว Google ไดรฟ์ API จะแจ้งให้แอปพลิเคชันทราบเมื่อมีการเปลี่ยนแปลงทรัพยากรที่ดู

ส่งคำขอรับชม

ทรัพยากร Google Drive API ที่ดูได้แต่ละรายการจะมีเมธอด watch ที่เชื่อมโยงอยู่ที่ URI ในรูปแบบต่อไปนี้

https://www.googleapis.com/API_NAME/API_VERSION/RESOURCE_PATH/watch

หากต้องการตั้งค่าแชแนลการแจ้งเตือนสำหรับข้อความเกี่ยวกับการเปลี่ยนแปลงทรัพยากรหนึ่งๆ ให้ส่งPOSTคำขอไปยังเมธอด watch ของทรัพยากรนั้น

ช่องทางการแจ้งเตือนแต่ละช่องจะเชื่อมโยงกับทั้งผู้ใช้และทรัพยากร (หรือชุดทรัพยากร) ที่เฉพาะเจาะจง คำขอ watch จะไม่สำเร็จ เว้นแต่ผู้ใช้ปัจจุบัน หรือบัญชีบริการ จะเป็นเจ้าของหรือมีสิทธิ์เข้าถึงทรัพยากรนี้

ตัวอย่าง

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีใช้ทรัพยากร channels เพื่อเริ่มดูการเปลี่ยนแปลงทรัพยากร files รายการเดียวโดยใช้วิธี files.watch

POST https://www.googleapis.com/drive/v3/files/fileId/watch
Authorization: Bearer CURRENT_USER_AUTH_TOKEN
Content-Type: application/json

{
  "id": "01234567-89ab-cdef-0123456789ab", // Your channel ID.
  "type": "web_hook",
  "address": "https://mydomain.com/notifications", // Your receiving URL.
  ...
  "token": "target=myApp-myFilesChannelDest", // (Optional) Your files channel token.
  "expiration": 1426325213000 // (Optional) Your requested channel expiration date and time.
}

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีใช้ทรัพยากร channels เพื่อเริ่มดู changes ทั้งหมดโดยใช้วิธี changes.watch

POST https://www.googleapis.com/drive/v3/changes/watch
Authorization: Bearer CURRENT_USER_AUTH_TOKEN
Content-Type: application/json

{
  "id": "4ba78bf0-6a47-11e2-bcfd-0800200c9a77", // Your channel ID.
  "type": "web_hook",
  "address": "https://mydomain.com/notifications", // Your receiving URL.
  ...
  "token": "target=myApp-myChangesChannelDest", // (Optional) Your changes channel token.
  "expiration": 1426325213000 // (Optional) Your requested channel expiration date and time.
}

พร็อพเพอร์ตี้ที่จำเป็น

คุณต้องระบุฟิลด์ต่อไปนี้ในคำขอ watch แต่ละรายการ

  • id สตริงพร็อพเพอร์ตี้ที่ระบุช่องทางการแจ้งเตือนใหม่นี้ ในโปรเจ็กต์ของคุณได้อย่างไม่ซ้ำกัน เราขอแนะนำให้ใช้ ตัวระบุที่ไม่ซ้ำกับผู้อื่น (UUID) หรือสตริงที่ไม่ซ้ำ ที่คล้ายกัน ความยาวสูงสุด 64 อักขระ

    ระบบจะส่งค่ารหัสที่คุณตั้งค่าไว้กลับมาใน X-Goog-Channel-Id ส่วนหัว HTTP ของข้อความ การแจ้งเตือนทุกข้อความที่คุณได้รับสำหรับช่องนี้

  • สตริงพร็อพเพอร์ตี้ type ที่ตั้งค่าเป็น web_hook

  • address สตริงพร็อพเพอร์ตี้ที่ตั้งค่าเป็น URL ที่รับฟัง และตอบกลับการแจ้งเตือนสำหรับช่องการแจ้งเตือนนี้ นี่คือ URL การเรียกกลับของเว็บบุ๊ก และต้องใช้ HTTPS

    โปรดทราบว่า Google Drive API จะส่งการแจ้งเตือนไปยังที่อยู่ HTTPS นี้ได้ก็ต่อเมื่อมีการติดตั้งใบรับรอง SSL ที่ถูกต้องในเว็บเซิร์ฟเวอร์ ใบรับรองที่ไม่ถูกต้องมีดังนี้

    • ใบรับรองแบบ Self-signed
    • ใบรับรองที่ลงนามโดยแหล่งที่มาที่ไม่น่าเชื่อถือ
    • ใบรับรองที่เพิกถอนไปแล้ว
    • ใบรับรองที่มีเรื่องไม่ตรงกับชื่อโฮสต์เป้าหมาย

พร็อพเพอร์ตี้ที่ไม่บังคับ

คุณยังระบุฟิลด์ที่ไม่บังคับเหล่านี้พร้อมกับwatchคำขอได้ด้วย

  • พร็อพเพอร์ตี้ token ที่ระบุค่าสตริงแบบสุ่ม เพื่อใช้เป็นโทเค็นช่อง คุณใช้โทเค็นช่องทางการแจ้งเตือน เพื่อวัตถุประสงค์ต่างๆ ได้ เช่น คุณสามารถใช้โทเค็น เพื่อยืนยันว่าข้อความขาเข้าแต่ละข้อความมีไว้สำหรับช่องทางที่แอปพลิเคชัน ของคุณสร้างขึ้น เพื่อให้แน่ใจว่าการแจ้งเตือนไม่ได้ถูก ปลอมแปลง หรือเพื่อกำหนดเส้นทางข้อความไปยังปลายทางที่ถูกต้องภายใน แอปพลิเคชันของคุณตามวัตถุประสงค์ของช่องทางนี้ ความยาวสูงสุด: 256 อักขระ

    โทเค็นจะรวมอยู่ในส่วนหัว HTTP X-Goog-Channel-Token ในข้อความการแจ้งเตือนทุกข้อความที่แอปพลิเคชันได้รับสำหรับช่องนี้

    หากใช้โทเค็นแชแนลการแจ้งเตือน เราขอแนะนำให้คุณทำดังนี้

    • ใช้รูปแบบการเข้ารหัสที่ขยายได้ เช่น พารามิเตอร์การค้นหาของ URL ตัวอย่าง: forwardTo=hr&createdBy=mobile

    • อย่าใส่ข้อมูลที่ละเอียดอ่อน เช่น โทเค็น OAuth

  • สตริงพร็อพเพอร์ตี้ expiration ที่ตั้งค่าเป็น การประทับเวลา Unix (เป็นมิลลิวินาที) ของวันที่และเวลาที่คุณต้องการให้ Google Drive API หยุดส่งข้อความสำหรับช่องทางการแจ้งเตือนนี้

    หากช่องมีเวลาหมดอายุ ระบบจะรวมเวลาดังกล่าวเป็นค่า ของX-Goog-Channel-Expirationส่วนหัว HTTP (ในรูปแบบที่มนุษย์อ่านได้ ) ในข้อความแจ้งเตือนทุกข้อความที่แอปพลิเคชัน ของคุณได้รับสำหรับช่องนี้

ดูรายละเอียดเพิ่มเติมเกี่ยวกับคำขอได้ที่เมธอด watch สำหรับเมธอด files และ changes ในการอ้างอิง API

การตอบกลับในนาฬิกา

หากwatchคำขอสร้างช่องการแจ้งเตือนสำเร็จ ระบบจะแสดงรหัสสถานะ HTTP 200 OK

เนื้อหาข้อความของการตอบกลับการดูจะให้ข้อมูลเกี่ยวกับ ช่องการแจ้งเตือนที่คุณเพิ่งสร้าง ดังตัวอย่างด้านล่าง

{
  "kind": "api#channel",
  "id": "01234567-89ab-cdef-0123456789ab"", // ID you specified for this channel.
  "resourceId": "o3hgv1538sdjfh", // ID of the watched resource.
  "resourceUri": "https://www.googleapis.com/drive/v3/files/o3hgv1538sdjfh", // Version-specific ID of the watched resource.
  "token": "target=myApp-myFilesChannelDest", // Present only if one was provided.
  "expiration": 1426325213000, // Actual expiration date and time as UNIX timestamp (in milliseconds), if applicable.
}

นอกจากพร็อพเพอร์ตี้ที่คุณส่งเป็นส่วนหนึ่งของคำขอแล้ว ข้อมูลที่ส่งคืนยังรวมถึง resourceId และ resourceUri เพื่อระบุแหล่งข้อมูลที่กำลังรับชมในช่องทางการแจ้งเตือนนี้ด้วย

คุณสามารถส่งข้อมูลที่ได้รับไปยังการดำเนินการช่องทางการแจ้งเตือนอื่นๆ ได้ เช่น เมื่อต้องการหยุดรับการแจ้งเตือน

ดูรายละเอียดเพิ่มเติมเกี่ยวกับการตอบกลับได้ที่เมธอด watch สำหรับเมธอด files และ changes ในการอ้างอิง API

ซิงค์ข้อความ

หลังจากสร้างช่องการแจ้งเตือนเพื่อดูทรัพยากรแล้ว Google Drive API จะส่งsyncข้อความเพื่อระบุว่าการแจ้งเตือนกำลังจะเริ่มขึ้น ค่าส่วนหัว HTTP ของ X-Goog-Resource-State สำหรับข้อความเหล่านี้คือ sync เนื่องจากปัญหาเกี่ยวกับเวลาของเครือข่าย คุณอาจได้รับsyncข้อความwatchก่อนที่จะได้รับการตอบกลับจากวิธีการwatch

คุณไม่จำเป็นต้องสนใจsyncการแจ้งเตือนนี้ แต่ก็ใช้ได้เช่นกัน ตัวอย่างเช่น หากคุณตัดสินใจว่าไม่ต้องการเก็บช่องไว้ คุณสามารถใช้ค่า X-Goog-Channel-ID และ X-Goog-Resource-ID ในการเรียกเพื่อหยุดรับการแจ้งเตือน นอกจากนี้ คุณยังใช้syncการแจ้งเตือนเพื่อทำการเริ่มต้นบางอย่างเพื่อเตรียมพร้อมสำหรับ เหตุการณ์ในภายหลังได้ด้วย

รูปแบบของข้อความ sync ที่ Google Drive API ส่งไปยัง URL ที่รับของคุณแสดงอยู่ด้านล่าง

POST https://mydomain.com/notifications // Your receiving URL.
X-Goog-Channel-ID: channel-ID-value
X-Goog-Channel-Token: channel-token-value
X-Goog-Channel-Expiration: expiration-date-and-time // In human-readable format. Present only if the channel expires.
X-Goog-Resource-ID: identifier-for-the-watched-resource
X-Goog-Resource-URI: version-specific-URI-of-the-watched-resource
X-Goog-Resource-State: sync
X-Goog-Message-Number: 1

ข้อความซิงค์จะมีค่าส่วนหัว HTTP X-Goog-Message-Number เป็น 1 เสมอ การแจ้งเตือนครั้งต่อๆ ไปสำหรับช่องนี้จะมีหมายเลขข้อความที่มากกว่าครั้งก่อนหน้า แต่หมายเลขข้อความจะไม่เรียงตามลำดับ

ต่ออายุช่องทางการแจ้งเตือน

แชแนลการแจ้งเตือนอาจมีเวลาหมดอายุ โดยมีค่า ที่กำหนดโดยคำขอของคุณหรือขีดจำกัดภายในของ Google ไดรฟ์ API หรือค่าเริ่มต้น (จะใช้ค่าที่จำกัดมากกว่า) เวลาหมดอายุของแชแนล หากมี จะรวมเป็นการประทับเวลา Unix (เป็นมิลลิวินาที) ในข้อมูลที่เมธอด watch แสดงผล นอกจากนี้ วันที่และเวลาหมดอายุ (ในรูปแบบที่มนุษย์อ่านได้) จะรวมอยู่ในข้อความแจ้งเตือนทุกข้อความที่แอปพลิเคชันของคุณได้รับสำหรับช่องนี้ในX-Goog-Channel-Expirationส่วนหัว HTTP

ปัจจุบันยังไม่มีวิธีต่ออายุช่องทางการแจ้งเตือนโดยอัตโนมัติ เมื่อ ช่องใกล้หมดอายุ คุณต้องแทนที่ด้วยช่องใหม่โดยเรียกใช้เมธอด watch คุณต้องใช้ค่าที่ไม่ซ้ำกันสำหรับพร็อพเพอร์ตี้ id ของช่องใหม่เสมอ โปรดทราบว่าอาจมีช่วงเวลาที่ "ทับซ้อนกัน" เมื่อช่องทางการแจ้งเตือน 2 ช่องสำหรับทรัพยากรเดียวกันทำงานอยู่

รับการแจ้งเตือน

เมื่อใดก็ตามที่ทรัพยากรที่ดูมีการเปลี่ยนแปลง แอปพลิเคชันของคุณจะได้รับข้อความแจ้งเตือนที่อธิบายการเปลี่ยนแปลงนั้น Google Drive API จะส่งข้อความเหล่านี้เป็นคำขอ HTTPS POST ไปยัง URL ที่คุณระบุเป็นพร็อพเพอร์ตี้ address สำหรับช่องทางการแจ้งเตือนนี้

ตีความรูปแบบข้อความแจ้งเตือน

ข้อความแจ้งเตือนทั้งหมดจะมีชุดส่วนหัว HTTP ที่มีคำนำหน้า X-Goog- การแจ้งเตือนบางประเภทอาจมี เนื้อหาข้อความด้วย

ส่วนหัว

ข้อความแจ้งเตือนที่ Google Drive API โพสต์ไปยัง URL ที่รับของคุณ จะมีส่วนหัว HTTP ต่อไปนี้

ส่วนหัว คำอธิบาย
พร้อมใช้งานเสมอ
X-Goog-Channel-ID UUID หรือสตริงอื่นๆ ที่ไม่ซ้ำกันที่คุณระบุเพื่อระบุช่องทางการแจ้งเตือนนี้
X-Goog-Message-Number จำนวนเต็มที่ระบุข้อความนี้สำหรับการแจ้งเตือน ช่อง ค่าจะเป็น 1 เสมอสำหรับข้อความ sync หมายเลข ข้อความจะเพิ่มขึ้นสำหรับข้อความถัดไปแต่ละข้อความในช่อง แต่ ไม่ได้เรียงตามลำดับ
X-Goog-Resource-ID ค่าทึบแสงที่ระบุทรัพยากรที่ดู รหัสนี้จะ คงที่ใน API ทุกเวอร์ชัน
X-Goog-Resource-State สถานะทรัพยากรใหม่ที่ทริกเกอร์การแจ้งเตือน ค่าที่เป็นไปได้ sync, add, remove, update trash, untrash หรือ change
X-Goog-Resource-URI ตัวระบุเฉพาะเวอร์ชัน API สำหรับทรัพยากรที่ดู
บางครั้ง
X-Goog-Changed รายละเอียดเพิ่มเติมเกี่ยวกับการเปลี่ยนแปลง ค่าที่เป็นไปได้ ได้แก่ content parents children หรือ permissions ไม่ได้ระบุข้อความ sync
X-Goog-Channel-Expiration วันที่และเวลาที่ช่องการแจ้งเตือนหมดอายุ ซึ่งแสดงใน รูปแบบที่มนุษย์อ่านได้ แสดงต่อเมื่อมีการกำหนด
X-Goog-Channel-Token โทเค็นแชแนลการแจ้งเตือนที่แอปพลิเคชันของคุณตั้งค่าไว้ และ ที่คุณใช้เพื่อยืนยันแหล่งที่มาของการแจ้งเตือนได้ แสดงต่อเมื่อมีการกำหนดไว้เท่านั้น

ข้อความแจ้งเตือนสำหรับ files และ changes ไม่มีข้อมูล

ตัวอย่าง

เปลี่ยนข้อความแจ้งเตือนสำหรับทรัพยากร files ซึ่งไม่มีเนื้อหาคำขอ

POST https://mydomain.com/notifications // Your receiving URL.
Content-Type: application/json; utf-8
Content-Length: 0
X-Goog-Channel-ID: 4ba78bf0-6a47-11e2-bcfd-0800200c9a66
X-Goog-Channel-Token: 398348u3tu83ut8uu38
X-Goog-Channel-Expiration: Tue, 19 Nov 2013 01:13:52 GMT
X-Goog-Resource-ID:  ret08u3rv24htgh289g
X-Goog-Resource-URI: https://www.googleapis.com/drive/v3/files/ret08u3rv24htgh289g
X-Goog-Resource-State:  update
X-Goog-Changed: content,properties
X-Goog-Message-Number: 10

ข้อความแจ้งเตือนการเปลี่ยนแปลงสำหรับทรัพยากร changes ซึ่งมีเนื้อหาของคำขอ

POST https://mydomain.com/notifications // Your receiving URL.
Content-Type: application/json; utf-8
Content-Length: 118
X-Goog-Channel-ID: 8bd90be9-3a58-3122-ab43-9823188a5b43
X-Goog-Channel-Token: 245t1234tt83trrt333
X-Goog-Channel-Expiration: Tue, 19 Nov 2013 01:13:52 GMT
X-Goog-Resource-ID:  ret987df98743md8g
X-Goog-Resource-URI: https://www.googleapis.com/drive/v3/changes
X-Goog-Resource-State:  changed
X-Goog-Message-Number: 23

{
  "kind": "drive#changes"
}

ตอบสนองต่อการแจ้งเตือนต่างๆ

หากต้องการระบุว่าสำเร็จ คุณสามารถแสดงรหัสสถานะต่อไปนี้ 200, 201, 202, 204 หรือ 102

หากบริการของคุณใช้ไลบรารีของไคลเอ็นต์ API ของ Google และแสดงผล 500,502, 503 หรือ 504, Google Drive API จะลองอีกครั้งด้วยการถอยแบบทวีคูณ รหัสสถานะการคืนสินค้าอื่นๆ ทั้งหมดจะถือว่าเป็นข้อความที่ไม่สำเร็จ

ทำความเข้าใจเหตุการณ์การแจ้งเตือนของ Google Drive API

ส่วนนี้ให้รายละเอียดเกี่ยวกับข้อความแจ้งที่คุณจะได้รับเมื่อใช้การแจ้งเตือนแบบพุชกับ Google Drive API

X-Goog-Resource-State ใช้กับ ส่งเมื่อ
sync files, changes สร้างช่องเรียบร้อยแล้ว คุณจะเริ่มได้รับการแจ้งเตือนสำหรับช่องดังกล่าว
add files มีการสร้างหรือแชร์ทรัพยากร
remove files แหล่งข้อมูลที่มีอยู่ถูกลบหรือยกเลิกการแชร์
update files มีการอัปเดตพร็อพเพอร์ตี้ (ข้อมูลเมตา) อย่างน้อย 1 รายการของทรัพยากร
trash files ย้ายทรัพยากรไปที่ถังขยะแล้ว
untrash files มีการนำทรัพยากรออกจากถังขยะ
change changes มีการเพิ่มรายการบันทึกการเปลี่ยนแปลงอย่างน้อย 1 รายการ

สำหรับเหตุการณ์ update อาจมีการระบุส่วนหัว HTTP ของ X-Goog-Changed ส่วนหัวนั้นมีรายการที่คั่นด้วยคอมมาซึ่งอธิบายประเภทของการเปลี่ยนแปลงที่เกิดขึ้น

ประเภทการเปลี่ยนแปลง ระบุ
content อัปเดตเนื้อหาของแหล่งข้อมูลแล้ว
properties มีการอัปเดตพร็อพเพอร์ตี้ของทรัพยากรอย่างน้อย 1 รายการ
parents มีการเพิ่มหรือนำองค์กรหลักของทรัพยากรอย่างน้อย 1 รายการออก
children มีการเพิ่มหรือนำทรัพยากรย่อยอย่างน้อย 1 รายการออก
permissions อัปเดตสิทธิ์ของทรัพยากรแล้ว

ตัวอย่างที่มีส่วนหัว X-Goog-Changed

X-Goog-Resource-State: update
X-Goog-Changed: content, permissions

ปิดการแจ้งเตือน

พร็อพเพอร์ตี้ expiration จะควบคุมเวลาที่การแจ้งเตือนจะหยุดโดยอัตโนมัติ คุณสามารถ เลือกหยุดรับการแจ้งเตือนสำหรับช่องหนึ่งๆ ก่อนที่การแจ้งเตือนนั้นจะหมดอายุได้ โดยการเรียกใช้เมธอด stop ที่ URI ต่อไปนี้

https://www.googleapis.com/drive/v3/channels/stop

วิธีนี้กำหนดให้คุณต้องระบุพร็อพเพอร์ตี้ id และ resourceId ของช่องเป็นอย่างน้อย ดังที่แสดงในตัวอย่างด้านล่าง โปรดทราบว่าหาก Google ไดรฟ์ API มีทรัพยากรหลายประเภทที่มีเมธอด watch จะมีเมธอด stop เพียงเมธอดเดียว

เฉพาะผู้ใช้ที่มีสิทธิ์ที่เหมาะสมเท่านั้นที่จะหยุดช่องได้ โดยเฉพาะอย่างยิ่งฟีเจอร์ต่อไปนี้

  • หากช่องสร้างขึ้นโดยบัญชีผู้ใช้ทั่วไป เฉพาะผู้ใช้รายเดียวกันจากไคลเอ็นต์เดียวกัน (ตามที่ระบุโดยรหัสไคลเอ็นต์ OAuth 2.0 จากโทเค็นการให้สิทธิ์) ที่สร้างช่องเท่านั้นที่จะหยุดช่องได้
  • หากช่องสร้างขึ้นโดยบัญชีบริการ ผู้ใช้จากไคลเอ็นต์เดียวกันจะหยุดช่องได้

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีหยุดรับการแจ้งเตือน

POST https://www.googleapis.com/drive/v3/channels/stop
  
Authorization: Bearer CURRENT_USER_AUTH_TOKEN
Content-Type: application/json

{
  "id": "4ba78bf0-6a47-11e2-bcfd-0800200c9a66",
  "resourceId": "ret08u3rv24htgh289g"
}