संपर्क
`contacts.list`, `get`, `create`, `save`, `update`, `set_audiences`, `delete`, `delete_many`, `list_people`, `set_photo`, `remove_photo`, `block`, `unblock`, `list_threads` और `activity`।
हर मेथड
page = client.contacts.list(limit: 100)contact = client.contacts.get("[email protected]") saved = client.contacts.create( email: "[email protected]", name: "Grace Hopper", notes: "Met at the compiler workshop") client.contacts.update("[email protected]", notes: nil)client.contacts.set_audiences("[email protected]", audienceIds: ["aud_4c1b8e2a7d9f05c36b4e8a71"])client.contacts.delete("[email protected]") puts page.items.size, page.has_more?, contact[:source], contact[:lastSeenAt], saved[:source]list सबसे हाल में दिखे संपर्क पहले लौटाता है, और जिन संपर्कों को कभी मेल नहीं भेजा गया उन्हें आख़िर में। source तब auto होता है जब पंक्ति इसलिए लिखी गई कि किसी सदस्य ने ऐप के composer से उस पते पर संदेश भेजा, जो किसी के उसे सहेजने से बिल्कुल अलग दावा है। किसी पते से आने वाला मेल कुछ नहीं लिखता, और इस API से किया गया send भी नहीं।
पता-पुस्तिका किसी एक व्यक्ति की नहीं, वर्कस्पेस की होती है, इसलिए किसी भी सदस्य द्वारा सहेजा गया संपर्क हर सदस्य और हर कुंजी को दिखता है। create source को manual लिखता है और संपर्क को लिखते समय ही डिफ़ॉल्ट ऑडियंस में डाल देता है। उसी कॉल में अपनी सूचियों से जोड़ने के लिए उनके नाम audienceIds में दें, जिसके लिए audiences:write भी चाहिए, या संपर्क को बाद में audiences.add_contact से जोड़ें, जिसे “ऑडियंस” पेज कवर करता है। set_audiences एक कॉल में ठीक-ठीक बताता है कि संपर्क किन सूचियों में है।
पते छोटे अक्षरों में सहेजे जाते हैं और gem आपके दिए पते को एन्कोड करता है, इसलिए [email protected] सही पंक्ति तक पहुँचता है। nil या ख़ाली पता कुछ भी भेजे जाने से पहले ArgumentError raise करता है। पता ही पहचान है, इसलिए update उसे नहीं बदल सकता: संपर्क को खिसकाना यानी एक delete और एक create।
पैरामीटर: contacts.list
limitInteger- हर पेज पर कितने संपर्क लौटाने हैं: 1 से 200 तक की पूर्ण संख्या, डिफ़ॉल्ट 50। इसका टाइप बदला जाता है, इसलिए query string से पढ़ी गई `"100"` जैसी String ठीक है, और सीमा से बाहर का मान सीमा में काटे जाने के बजाय 422 है।
cursorString- पिछले पेज का `next_cursor`। इसे कभी ख़ुद न बनाएँ: जो cursor किसी ऐसे संपर्क का नाम लेता है जो अब मौजूद नहीं, वह 400 `invalid_cursor` है, जो `OpenEmail::InvalidRequestError` के रूप में raise होता है, और इसका मतलब है कि आपकी पेजिंग स्थिति पुरानी हो चुकी है और चलना बिना cursor के फिर से शुरू होना चाहिए।
sourceString- जानबूझकर सहेजे गए संपर्कों के लिए `manual`, ऐप के composer द्वारा दर्ज संपर्कों के लिए `auto`। पूरी पुस्तिका के लिए इसे छोड़ दें।
qString- नाम और पते में खोजता है, 200 अक्षरों तक। अगर पहले पेज पर कुछ भी ठीक-ठीक मेल न खाए, तो उसकी जगह मिलती-जुलती वर्तनियाँ लौटती हैं, और आगे के पेज उसी तरह मिलान करते रहते हैं।
जवाब: एक संपर्क
contacts.list एक OpenEmail::Page लौटाता है, इसलिए पंक्तियाँ page.items पर होती हैं और जब तक page.has_more? true है, चलना page.next_cursor का पीछा करता है। list_all हर पंक्ति एक Array के रूप में लौटाता है, और iterate उन्हें एक-एक करके yield करता है। get, create, update, save और set_audiences हर एक एक संपर्क Symbol कुंजियों वाले Hash के रूप में लौटाते हैं, वही पंक्ति, साथ में audiences। पता-पुस्तिका की कोई सीमा नहीं है, इसीलिए यह route ऐसी Array लौटाने के बजाय पेज करता है जो चुपचाप 200 पर रुक गई हो।
objectString- हमेशा स्ट्रिंग `contact`, list की पंक्तियों पर भी और `get` पर भी।
emailString- पता, लिखते समय छोटे अक्षरों में बदला हुआ, ताकि `[email protected]` और `[email protected]` एक ही contact हों; और यही वह कुंजी है जो हर contacts method लेता है, क्योंकि कोई contact id उजागर नहीं की जाती। पंक्तियाँ उस सदस्य या कुंजी की नहीं होतीं जिसने उन्हें लिखा, बल्कि workspace की होती हैं, इसलिए workspace के हर सदस्य और हर कुंजी के लिए एक ही पता-पुस्तिका है।
nameString or nil- display name, या nil जब उस पते के लिए कभी कोई नाम दर्ज न हुआ हो। अपने-आप होने वाला write नाम तभी लाता है जब हेडर ने पते के अलावा कुछ दिया हो, और वह उपयोगकर्ता द्वारा टाइप किए नाम को कभी नहीं बदल सकता।
sourceString- `auto` का मतलब है कि पंक्ति इसलिए लिखी गई कि उपयोगकर्ता ने उस पते पर मेल भेजा। `manual` का मतलब है कि किसी ने इसे हाथ से दर्ज किया, जो बिल्कुल अलग दावा है, और कोई upsert कभी `manual` को वापस `auto` नहीं बनाता। किसी पते से आने वाला मेल जानबूझकर कोई पंक्ति नहीं लिखता, इसलिए जिसने सिर्फ़ आपको लिखा है वह यहाँ नहीं है। इस मान को खुली String मानें, क्योंकि यह कॉलम `manual` डिफ़ॉल्ट वाला मुक्त टेक्स्ट है।
notesString or nil- किसी ने इस व्यक्ति के बारे में जो मुक्त टेक्स्ट लिखा, ऐप में या `update` के ज़रिए, कभी अपने-आप बना नहीं। जब किसी ने कुछ नहीं लिखा तो यह nil है, और `update` पर `notes: nil` इसे साफ़ कर देता है।
lastSeenAtString or nil- एक ISO 8601 UTC स्ट्रिंग, जो हर बार आगे बढ़ती है जब कोई सदस्य ऐप के composer से उस पते पर भेजता है, न कि जब उससे मेल आता है, जो कुछ नहीं लिखता। `create` से सहेजे गए उस संपर्क पर यह nil है जिसे कभी मेल नहीं भेजा गया, और ऐसे संपर्क इस route के लौटाए घटते `lastSeenAt` क्रम में आख़िर में आते हैं।
audiencesArray<Hash>- सिर्फ़ `get`, `create`, `update`, `save` और `set_audiences` पर, सूची की पंक्तियों पर कभी नहीं। हर ऑडियंस जिसमें संपर्क है, डिफ़ॉल्ट वाली समेत, `id`, `name` और `builtin` वाले Hash के रूप में। जिस ऑडियंस में हर संपर्क होता है उस पर `builtin` `default` है और किसी की बनाई ऑडियंस पर nil, इसलिए शाखा नाम पर नहीं, इस पर बनाएँ, क्योंकि नाम कोई भी बदल सकता है।
photoUrlString or nil- संपर्क की फ़ोटो कहाँ से दी जाती है, या संपर्क की कोई फ़ोटो न हो तो nil। `set_photo` इसे सेट करता है और हर अपलोड को नया URL मिलता है।
किसी संपर्क की ऑडियंस सेट करना
set_audiences(email, audienceIds: [...]) एक रिक्वेस्ट में ठीक-ठीक बताता है कि एक संपर्क किन ऑडियंस में है। संपर्क हर उस सूचीबद्ध ऑडियंस में जुड़ता है जिसमें वह अभी नहीं है और बाक़ी हर एक को छोड़ देता है, और कॉल बदलाव के बाद संपर्क को उसकी audiences के साथ लौटाती है। इसे audiences:write चाहिए, क्योंकि यह संपर्क नहीं, सदस्यताएँ लिखता है, और इसे दोहराने से कुछ नहीं बदलता, इसलिए gem नेटवर्क विफलता के बाद इस पर पुनः प्रयास करता है।
डिफ़ॉल्ट ऑडियंस हमेशा रखी जाती है, इसलिए audienceIds: [] संपर्क को सिर्फ़ डिफ़ॉल्ट ऑडियंस में छोड़ देता है। यह 100 तक ids लेता है। जो id इस वर्कस्पेस की किसी ऑडियंस का नाम नहीं लेती वह 404 audience_not_found है और कुछ नहीं बदलता, और जो पता संपर्क नहीं है वह 404 contact_not_found है। दोनों OpenEmail::NotFoundError raise करते हैं।
संपर्क पेज के सभी लोग
list_people उन लोगों को सूचीबद्ध करता है जिन्हें ऐप का “संपर्क” पेज दिखाता है: सहेजे गए संपर्क और मेल में दिखा हर पता, हर एक saved, threads और lastAt के साथ। list सिर्फ़ सहेजे गए संपर्क हैं। यह एक OpenEmail::PeoplePage लौटाता है, जो items, has_more? और next_cursor में seen जोड़ता है। मेल में दिखे पते तभी आते हैं जब कुंजी के पास threads:read भी हो, और page.seen बताता है कि आए या नहीं। sort: recent, name या threads है, और OpenEmail::PEOPLE_SORTS उनके नाम बताता है। q: नाम, पते और नोट्स में खोजता है, और blocked: true उन लोगों को रखता है जिन्हें वर्कस्पेस की blocklist रोकती है, पूरे डोमेन वाले नियमों समेत। blockedBy हर पंक्ति पर नियम का नाम बताता है।
page = client.contacts.list_people(sort: "threads", limit: 50) page.items.each do |person| client.contacts.save(person[:email]) if !person[:saved] && person[:threads].to_i > 5end blocked = client.contacts.list_all_people(blocked: true)puts page.seen, blocked.sizelist_all_people हर पेज एक Array के रूप में लौटाता है, और iterate_people हर व्यक्ति को block में yield करता है, या block के बिना एक Enumerator लौटाता है। दोनों में से कोई seen नहीं बताता, इसलिए उसे जानने के लिए list_people से एक पेज पढ़ें। cursor अपारदर्शी है, इसलिए next_cursor को ठीक वैसा ही, उन्हीं sort:, q: और blocked: के साथ, cursor: के रूप में वापस भेजें।
सहेजना, हटाना और फ़ोटो
save(email), वैकल्पिक name: और notes: के साथ, “संपर्कों में जोड़ें” और “संपर्कों में रखें” है: यह ऐसा पता सहेजता है जो अभी संपर्क नहीं है, send से दर्ज हुए पते को हाथ से सहेजे गए के रूप में रखता है, और हटाए गए पते को वापस लाता है। delete “हटाएँ” है: यह सहेजा गया संपर्क हटाता है और पते को छिपा देता है, ताकि composer उसे फिर दर्ज न करे, और यह सिर्फ़ मेल में दिखे पते को भी लेता है। इसके लौटाए Hash में wasSaved बताता है कि वह कौन-सा था। delete_many एक कॉल में 200 तक हटाता है।
client.contacts.save("[email protected]", name: "Grace Hopper") contact = client.contacts.set_photo("[email protected]", File.binread("photo.jpg"), content_type: "image/jpeg")puts contact[:photoUrl] client.contacts.set_photo("[email protected]", Pathname("photo.png")) client.contacts.remove_photo("[email protected]")client.contacts.delete_many(["[email protected]", "[email protected]"])set_photo चित्र के बाइट्स जैसे हैं वैसे भेजता है: PNG, JPEG, WebP या GIF, 5 MB तक, 512 पिक्सेल के वर्ग में फ़िट किए हुए। बाइट्स binary String, IO या Pathname होते हैं। content_type: पास करें, या ऐसे बाइट्स जो अपना टाइप साथ लाते हैं: ऐसा ऑब्जेक्ट जो content_type का जवाब दे, जैसे Rails अपलोड, या ऐसी File या Pathname जिसका नाम .png, .jpg, .jpeg, .webp या .gif पर ख़त्म हो। टाइप के बिना बाइट्स application/octet-stream के रूप में जाते हैं, जिसे सर्वर 422 invalid_image के साथ अस्वीकार करता है। OpenEmail::CONTACT_PHOTO_TYPES चारों टाइप के नाम बताता है। पता पहले एक सहेजा गया संपर्क होना चाहिए।
ब्लॉक करना
block(email) पते को वर्कस्पेस की ब्लॉक सूची में डालता है ताकि उससे आने वाला मेल अस्वीकार हो, कोई भी प्लस टैग हटाकर, और unblock(email) उसे ब्लॉक करने वाला हर नियम हटाता है। दोनों को settings:write चाहिए, क्योंकि वे संपर्क नहीं बल्कि ब्लॉक सूची बदलते हैं, और किसी के लिए पते का संपर्क होना ज़रूरी नहीं।
जब unblock पूरे डोमेन वाला नियम हटाता है, तो removed उसे list का मान blockedDomains रखकर सूचीबद्ध करता है, और उस डोमेन के सभी लोग उसके साथ unblock हो जाते हैं। OpenEmail::CONTACT_BLOCK_LISTS दोनों सूचियों के नाम बताता है।
बातचीत और गतिविधि
list_threads(email) उन थ्रेड को पेज करता है जिनमें उस पते ने लिखा या जिनमें उसे लिखा गया, हर फ़ोल्डर में, और list_all_threads तथा iterate_threads उन पर चलते हैं। activity(email) किसी संपर्क के “गतिविधि” टैब के पीछे के आँकड़े लौटाता है: हर बकेट में प्राप्त और भेजे गए, आपके जवाब का इंतज़ार कर रहे थ्रेड, और दोनों दिशाओं में जवाब के समय की माध्यिका। दोनों को threads:read चाहिए।
threads = client.contacts.list_threads("[email protected]", q: "invoice") activity = client.contacts.activity( "[email protected]", minutes: 30 * 24 * 60, grain: "day", offset_minutes: Time.now.utc_offset / 60) puts threads.items.size, activity.dig(:totals, :waiting)activity snake_case keywords लेता है। minutes: विंडो तय करता है, जो छोड़ने पर 90 दिन होती है। grain: बकेट की चौड़ाई तय करता है: minute, hour या day। offset_minutes: UTC से पूर्व में मिनट तय करता है जहाँ दिन बदलते हैं। Time.now.utc_offset / 60 स्थानीय offset है, और gem इसे API के offsetMinutes के रूप में भेजता है।