1/*
2
3hangouts.proto - Unofficial, reverse engineered Protocol Buffers for Google's
4Hangouts chat protocol.
5
6Originally based on Darryl Pogue's reversed engineered proto file from an early
7version of Hangouts for Android: https://gist.github.com/dpogue/5692114
8
9Field and message name should generally match those used by Google, with the
10major exception that "Client" prefixes have been removed.
11
12 */
13
14// proto2 is required because we need to be able to serialize default values:
15syntax = "proto2";
16
17// Describes which Hangouts client is active.
18enum ActiveClientState {
19  // No client is active.
20  ACTIVE_CLIENT_STATE_NO_ACTIVE = 0;
21  // This is the active client.
22  ACTIVE_CLIENT_STATE_IS_ACTIVE = 1;
23  // Other client is active.
24  ACTIVE_CLIENT_STATE_OTHER_ACTIVE = 2;
25}
26
27// The state of do-not-disturb mode. Not to be confused with DndSetting, which
28// is used to change the state of do-not-disturb mode.
29message DoNotDisturbSetting {
30  // Whether do-not-disturb mode is enabled.
31  optional bool do_not_disturb = 1;
32  // Timestamp when do-not-disturb mode expires.
33  optional uint64 expiration_timestamp = 2;
34  // Timestamp when this setting was applied. Not present when this message
35  // comes from a notification.
36  optional uint64 version = 3;
37}
38
39message NotificationSettings {
40  optional DoNotDisturbSetting dnd_settings = 1;
41}
42
43enum FocusType {
44  FOCUS_TYPE_UNKNOWN = 0;
45  FOCUS_TYPE_FOCUSED = 1;
46  FOCUS_TYPE_UNFOCUSED = 2;
47}
48
49enum FocusDevice {
50  FOCUS_DEVICE_UNSPECIFIED = 0;
51  FOCUS_DEVICE_DESKTOP = 20;
52  FOCUS_DEVICE_MOBILE = 300;
53}
54
55// Identifies a conversation.
56message ConversationId {
57  // Unique identifier for a conversation.
58  optional string id = 1;
59}
60
61// Identifies a user.
62message ParticipantId {
63  // Unique identifier for a user's Google account.
64  optional string gaia_id = 1;
65  // Seems to always be the same as gaia_id.
66  optional string chat_id = 2;
67}
68
69// Indicates whether Hangouts is active (running in the foreground) on
70// different types of devices.
71message DeviceStatus {
72  // True if a mobile phone is active.
73  optional bool mobile = 1;
74  // True if a desktop or laptop is active.
75  optional bool desktop = 2;
76  // True if a tablet is active.
77  optional bool tablet = 3;
78}
79
80message LastSeen {
81  required uint64 last_seen_timestamp = 1; //in microseconds
82  optional uint64 usec_since_last_seen = 2;
83}
84
85message Location {
86  optional uint64 type = 1;
87  optional double lat = 2;
88  optional double lng = 3;
89  optional uint64 timestamp_msec = 4;
90  optional uint64 accuracy_meters = 5;
91  optional string display_name = 6;
92}
93
94enum CallType {
95  CALL_TYPE_NONE = 0;
96  CALL_TYPE_PSTN = 1;
97  CALL_TYPE_HANGOUT = 2;
98}
99
100message InCall {
101  optional CallType call_type = 1;
102}
103
104message Presence {
105  optional bool reachable = 1;
106  optional bool available = 2;
107  repeated Location device_location = 3;
108  optional InCall in_call = 5;
109  optional DeviceStatus device_status = 6;
110  optional MoodSetting mood_setting = 9;
111  optional LastSeen last_seen = 10;
112
113  //TODO
114  //optional RichStatus rich_status = 4;
115  //optional DeviceActivity device_activity = 7;
116}
117
118message PresenceResult {
119  optional ParticipantId user_id = 1;
120  optional Presence presence = 2;
121}
122
123enum TypingType {
124  TYPING_TYPE_UNKNOWN = 0;
125  // Started typing.
126  TYPING_TYPE_STARTED = 1;
127  // Stopped typing with inputted text.
128  TYPING_TYPE_PAUSED = 2;
129  // Stopped typing with no inputted text.
130  TYPING_TYPE_STOPPED = 3;
131}
132
133message ClientIdentifier {
134  // (client_id in hangups).
135  optional string resource = 1;
136  // unknown (header_id in hangups).
137  optional string client_id = 2;
138  //optional string self_fanout_id = 3;
139  optional string participant_log_id = 4;
140}
141
142enum ClientPresenceStateType {
143  CLIENT_PRESENCE_STATE_UNKNOWN = 0;
144  CLIENT_PRESENCE_STATE_NONE = 1;
145  CLIENT_PRESENCE_STATE_MOBILE = 10;
146  CLIENT_PRESENCE_STATE_MOBILE_ACTIVE = 20;
147  CLIENT_PRESENCE_STATE_DESKTOP_IDLE = 30;
148  CLIENT_PRESENCE_STATE_DESKTOP_ACTIVE = 40;
149}
150
151message ClientPresenceState {
152  optional ClientIdentifier identifier = 1;
153  optional ClientPresenceStateType state = 2;
154  optional uint64 expiration_timestamp = 3;
155}
156
157enum NotificationLevel {
158  NOTIFICATION_LEVEL_UNKNOWN = 0;
159  // Notifications are disabled.
160  NOTIFICATION_LEVEL_QUIET = 10;
161  NOTIFICATION_LEVEL_DING = 20;
162  //NOTIFICATION_LEVEL_IMPORTANT_ONLY = 25;
163  // Notifications are enabled.
164  NOTIFICATION_LEVEL_RING = 30;
165  //NOTIFICATION_LEVEL_USE_GLOBAL_DEFAULT = 100;
166}
167
168message UserEventState {
169  optional ParticipantId user_id = 1;
170  optional string client_generated_id = 2;
171  optional NotificationLevel notification_level = 3;
172}
173
174enum SegmentType {
175  // Segment is text.
176  SEGMENT_TYPE_TEXT = 0;
177  // Segment is a line break.
178  SEGMENT_TYPE_LINE_BREAK = 1;
179  // Segment is hyperlinked text.
180  SEGMENT_TYPE_LINK = 2;
181  //SEGMENT_TYPE_USER_MENTION = 3;
182  //SEGMENT_TYPE_HASHTAG = 4;
183  //SEGMENT_TYPE_ALL_USER_MENTION = 5;
184}
185
186message Formatting {
187  optional bool bold = 1;
188  optional bool italics = 2;
189  optional bool strikethrough = 3;
190  optional bool underline = 4;
191}
192
193message LinkData {
194  optional string link_target = 1;
195}
196
197// message UserMentionData {
198  // optional int64 user_gaia_id = 1;
199  // optional string user_id = 2;
200  // optional string email = 3;
201// }
202
203// message HashtagData {
204  // optional string search_text = 1;
205// }
206
207// A segment of a message. Message are broken into segments that may be of
208// different types and have different formatting.
209message Segment {
210  // Note: This field is required because Hangouts for Chrome misbehaves if it
211  // isn't serialized.
212  required SegmentType type = 1;
213  // The segment text. For line breaks, may either be empty or contain new line
214  // character.
215  optional string text = 2;
216  // Formatting for this segment.
217  optional Formatting formatting = 3;
218  // Link data for this segment, if it is a link.
219  optional LinkData link_data = 4;
220  //optional UserMentionData user_mention_data = 5;
221  //optional HashtagData hashtag_data = 6;
222}
223
224// A type of embedded item.
225enum ItemType {
226  ITEM_TYPE_THING = 0;
227  // Google Plus photo.
228  ITEM_TYPE_PLUS_PHOTO = 249;
229  ITEM_TYPE_PLACE = 335;
230  // Google Map place.
231  ITEM_TYPE_PLACE_V2 = 340;
232}
233
234// Google Plus photo that can be embedded in a chat message.
235message PlusPhoto {
236
237  // Metadata for displaying an image thumbnail.
238  message Thumbnail {
239
240    // URL to navigate to when thumbnail is selected (a Google Plus album
241    // page).
242    optional string url = 1;
243    // URL of thumbnail image.
244    optional string image_url = 4;
245    // Image width in pixels.
246    optional uint64 width_px = 10;
247    // Image height in pixels.
248    optional uint64 height_px = 11;
249  }
250
251  // Media type.
252  enum MediaType {
253    MEDIA_TYPE_UNKNOWN = 0;
254    MEDIA_TYPE_PHOTO = 1;
255    MEDIA_TYPE_VIDEO = 2;
256    MEDIA_TYPE_ANIMATED_PHOTO = 4;
257  }
258
259  // Thumbnail.
260  optional Thumbnail thumbnail = 1;
261  // Owner obfuscated ID.
262  optional string owner_obfuscated_id = 2;
263  // Album ID.
264  optional string album_id = 3;
265  // Photo ID.
266  optional string photo_id = 4;
267  // URL of full-sized image.
268  optional string url = 6;
269  // URL of image thumbnail.
270  optional string original_content_url = 10;
271  // The media type.
272  optional MediaType media_type = 13;
273  // List of stream ID parameters.
274  repeated string stream_id = 14;
275  // The download URL for a video
276  optional string download_url = 20;
277}
278
279// Place that can be embedded in a chat message via Google Maps.
280message Place {
281
282  // Representative image of a place.
283  message RepresentativeImage {
284    // URL of image.
285    optional string url = 2;
286  }
287
288  // Google Maps URL pointing to the map coordinates.
289  optional string url = 1;
290  // Name of map location.
291  optional string name = 3;
292  // Representative image of the place (map with pin).
293  optional RepresentativeImage representative_image = 185;
294}
295
296// An item of some type embedded in a chat message.
297message EmbedItem {
298  // List of embedded item types in this message.
299  repeated ItemType type = 1;
300  // For photos this is not given, for maps, it's the URL of the map.
301  optional string id = 2;
302  // Embedded Google Plus photo.
303  optional PlusPhoto plus_photo = 27639957;
304  // Embedded Google Map of a place.
305  optional Place place = 35825640;
306}
307
308// An attachment for a chat message.
309message Attachment {
310  optional EmbedItem embed_item = 1;
311}
312
313// Chat message content.
314message MessageContent {
315  repeated Segment segment = 1;
316  repeated Attachment attachment = 2;
317}
318
319// Annotation that can be applied to a chat message event. The only known use
320// for this is "\me" actions supported by the Chrome client (type 4).
321message EventAnnotation {
322  // Annotation type.
323  optional int32 type = 1;
324  // Optional annotation string value.
325  optional string value = 2;
326}
327
328// A chat message in a conversation.
329message ChatMessage {
330  // Optional annotation to attach to message.
331  repeated EventAnnotation annotation = 2;
332  // The message's content.
333  optional MessageContent message_content = 3;
334
335  // TODO:
336  // always 0? = 1;
337}
338
339enum MembershipChangeType {
340  MEMBERSHIP_CHANGE_TYPE_JOIN = 1;
341  MEMBERSHIP_CHANGE_TYPE_LEAVE = 2;
342}
343
344message Participant {
345  optional ParticipantId id = 1;
346  optional string first_name = 2;
347  optional string full_name = 3;
348  optional string profile_photo_url = 4;
349}
350
351enum LeaveReason {
352 LEAVE_REASON_UNKNOWN = 0;
353 LEAVE_REASON_HISTORY_POLICY_CHANGE = 1;
354 LEAVE_REASON_USER_INITIATED = 2;
355}
356
357message MembershipChange {
358  optional MembershipChangeType type = 1;
359  repeated Participant participant = 2;
360  repeated ParticipantId participant_ids = 3;
361  optional LeaveReason leave_reason = 4;
362}
363
364message ConversationRename {
365  optional string new_name = 1;
366  optional string old_name = 2;
367}
368
369enum HangoutEventType {
370  HANGOUT_EVENT_TYPE_UNKNOWN = 0;
371  HANGOUT_EVENT_TYPE_START = 1;
372  HANGOUT_EVENT_TYPE_END = 2;
373  HANGOUT_EVENT_TYPE_JOIN = 3;
374  HANGOUT_EVENT_TYPE_LEAVE = 4;
375  HANGOUT_EVENT_TYPE_COMING_SOON = 5;
376  HANGOUT_EVENT_TYPE_ONGOING = 6;
377}
378
379enum HangoutMediaType {
380  HANGOUT_MEDIA_TYPE_UNKNOWN = 0;
381  HANGOUT_MEDIA_TYPE_AUDIO_VIDEO = 1;
382  HANGOUT_MEDIA_TYPE_AUDIO_ONLY = 2;
383  HANGOUT_MEDIA_TYPE_PUSH_TO_TALK = 3;
384}
385
386message HangoutEvent {
387  optional HangoutEventType event_type = 1;
388  repeated ParticipantId participant_id = 2;
389  optional uint64 hangout_duration_secs = 3;
390  optional ConversationId transferred_conversation_id = 4;
391  optional uint64 refresh_timeout_secs = 5;
392  optional bool is_peridoic_refresh = 6;
393  optional HangoutMediaType media_type = 7;
394}
395
396message OTRModification {
397  optional OffTheRecordStatus old_otr_status = 1;
398  optional OffTheRecordStatus new_otr_status = 2;
399  optional OffTheRecordToggle old_otr_toggle = 3;
400  optional OffTheRecordToggle new_otr_toggle = 4;
401}
402
403// Whether the OTR toggle is available to the user.
404enum OffTheRecordToggle {
405  OFF_THE_RECORD_TOGGLE_UNKNOWN = 0;
406  OFF_THE_RECORD_TOGGLE_ENABLED = 1;
407  OFF_THE_RECORD_TOGGLE_DISABLED = 2;
408}
409
410enum OffTheRecordStatus {
411  OFF_THE_RECORD_STATUS_UNKNOWN = 0;
412  // Conversation is off-the-record (history disabled).
413  OFF_THE_RECORD_STATUS_OFF_THE_RECORD = 1;
414  // Conversation is on-the-record (history enabled).
415  OFF_THE_RECORD_STATUS_ON_THE_RECORD = 2;
416}
417
418enum SourceType {
419  SOURCE_TYPE_UNKNOWN = 0;
420  SOURCE_TYPE_MOBILE = 1;
421  SOURCE_TYPE_WEB = 2;
422}
423
424enum EventType {
425  EVENT_TYPE_UNKNOWN = 0;
426  EVENT_TYPE_REGULAR_CHAT_MESSAGE = 1;
427  EVENT_TYPE_SMS = 2;
428  EVENT_TYPE_VOICEMAIL = 3;
429  EVENT_TYPE_ADD_USER = 4;
430  EVENT_TYPE_REMOVE_USER = 5;
431  EVENT_TYPE_CONVERSATION_RENAME = 6;
432  EVENT_TYPE_HANGOUT = 7;
433  EVENT_TYPE_PHONE_CALL = 8;
434  EVENT_TYPE_OTR_MODIFICATION = 9;
435  EVENT_TYPE_PLAN_MUTATION = 10; //DEPRECATED_10
436  EVENT_TYPE_MMS = 11;
437  EVENT_TYPE_DEPRECATED_12 = 12;
438  EVENT_TYPE_OBSERVED_EVENT = 13;
439  EVENT_TYPE_GROUP_LINK_SHARING_MODIFICATION = 14;
440}
441
442message HashModifier {
443  optional string update_id = 1;
444  optional uint64 hash_diff = 2;
445  optional uint64 version = 4;
446}
447
448// Event that becomes part of a conversation's history.
449message Event {
450  // ID of the conversation this event belongs to.
451  optional ConversationId conversation_id = 1;
452  // ID of the user that sent this event.
453  optional ParticipantId sender_id = 2;
454  // Timestamp when the event occurred.
455  optional uint64 timestamp = 3;
456  optional UserEventState self_event_state = 4;
457  optional SourceType source_type = 6;
458  optional ChatMessage chat_message = 7;
459  optional MembershipChange membership_change = 9;
460  optional ConversationRename conversation_rename = 10;
461  optional HangoutEvent hangout_event = 11;
462  // Unique ID for the event.
463  optional string event_id = 12;
464  optional uint64 expiration_timestamp = 13;
465  optional OTRModification otr_modification = 14;
466  optional bool advances_sort_timestamp = 15;
467  optional OffTheRecordStatus event_otr = 16;
468  optional bool persisted = 17;
469  optional DeliveryMedium delivery_medium = 20;
470  // The event's type.
471  optional EventType event_type = 23;
472  // Event version timestamp.
473  optional uint64 event_version = 24;
474  optional HashModifier hash_modifier = 26;
475  optional GroupLinkSharingModification group_link_sharing_modification = 31;
476}
477
478enum ConversationType {
479  CONVERSATION_TYPE_UNKNOWN = 0;
480  // Conversation is one-to-one (only 2 participants).
481  CONVERSATION_TYPE_ONE_TO_ONE = 1;
482  // Conversation is group (any number of participants).
483  CONVERSATION_TYPE_GROUP = 2;
484}
485
486message UserReadState {
487  optional ParticipantId participant_id = 1;
488  optional uint64 latest_read_timestamp = 2;
489
490  // TODO: is latest_read_timestamp always 0?
491}
492
493enum ConversationStatus {
494  CONVERSATION_STATUS_UNKNOWN = 0;
495  // User is invited to conversation.
496  CONVERSATION_STATUS_INVITED = 1;
497  // User is participating in conversation.
498  CONVERSATION_STATUS_ACTIVE = 2;
499  // User has left conversation.
500  CONVERSATION_STATUS_LEFT = 3;
501}
502
503enum ConversationView {
504  CONVERSATION_VIEW_UNKNOWN = 0;
505  // Conversation is in inbox.
506  CONVERSATION_VIEW_INBOX = 1;
507  // Conversation has been archived.
508  CONVERSATION_VIEW_ARCHIVED = 2;
509}
510
511enum DeliveryMediumType {
512  DELIVERY_MEDIUM_UNKNOWN = 0;
513  DELIVERY_MEDIUM_BABEL = 1;
514  DELIVERY_MEDIUM_GOOGLE_VOICE = 2;
515  DELIVERY_MEDIUM_LOCAL_SMS = 3;
516}
517
518message DeliveryMedium {
519  optional DeliveryMediumType medium_type = 1;
520  // Phone number to use for sending Google Voice messages.
521  optional PhoneNumber self_phone = 2;
522}
523
524message DeliveryMediumOption {
525  optional DeliveryMedium delivery_medium = 1;
526  optional bool current_default = 2;
527  optional bool primary = 3;
528}
529
530enum InvitationAffinity {
531  INVITE_AFFINITY_UNKNOWN = 0;
532  INVITE_AFFINITY_HIGH = 1;
533  INVITE_AFFINITY_LOW = 2;
534}
535
536message UserConversationState {
537   optional string client_generated_id = 2;
538   optional UserReadState self_read_state = 7;
539   optional ConversationStatus status = 8;
540   optional NotificationLevel notification_level = 9;
541   repeated ConversationView view = 10;
542   optional ParticipantId inviter_id = 11;
543   optional uint64 invite_timestamp = 12;
544   optional uint64 sort_timestamp = 13;
545   optional uint64 active_timestamp = 14;
546   optional InvitationAffinity invite_affinity = 15;
547   //optional bool has_no_persistent_events = 16;
548   repeated DeliveryMediumOption delivery_medium_option = 17;
549   //optional bool is_guest = 21;
550}
551
552enum ParticipantType {
553  PARTICIPANT_TYPE_UNKNOWN = 0;
554  //PARTICIPANT_TYPE_INVALID = 1;
555  PARTICIPANT_TYPE_GAIA = 2;
556  PARTICIPANT_TYPE_OFF_NETWORK_PHONE = 3;
557  //PARTICIPANT_TYPE_MALFORMED_PHONE_NUMBER = 4;
558  //PARTICIPANT_TYPE_UNKNOWN_PHONE_NUMBER = 5;
559  //PARTICIPANT_TYPE_ANONYMOUS_PHONE_NUMBER = 6;
560}
561
562enum InvitationStatus {
563  INVITATION_STATUS_UNKNOWN = 0;
564  INVITATION_STATUS_PENDING = 1;
565  INVITATION_STATUS_ACCEPTED = 2;
566  INVITATION_STATUS_NEEDED = 3;
567}
568
569message ConversationParticipantData {
570  optional ParticipantId id = 1;
571  optional string fallback_name = 2;
572  optional InvitationStatus invitation_status = 3;
573  optional PhoneNumber phone_number = 4;
574  optional ParticipantType participant_type = 5;
575  optional InvitationStatus new_invitation_status = 6;
576}
577
578enum ForceHistory {
579  FORCE_HISTORY_UNKNOWN = 0;
580  FORCE_HISTORY_NO = 1;
581  //FORCE_HISTORY_ON = 2;
582  //FORCE_HISTORY_OFF = 3;
583}
584
585enum NetworkType { //ER is this the same as DeliveryMediumType ?
586  NETWORK_TYPE_UNKNOWN = 0;
587  NETWORK_TYPE_BABEL = 1;
588  NETWORK_TYPE_PHONE = 2;
589}
590
591// A conversation between two or more users.
592message Conversation {
593  optional ConversationId conversation_id = 1;
594  optional ConversationType type = 2;
595  optional string name = 3;
596  optional UserConversationState self_conversation_state = 4;
597  //repeated bytes deprecated5 = 5;
598  //repeated bytes deprecated6 = 6;
599  repeated UserReadState read_state = 8;
600  // True if the conversation has an active Hangout.
601  optional bool has_active_hangout = 9;
602  // The conversation's "off the record" status.
603  optional OffTheRecordStatus otr_status = 10;
604  // Whether the OTR toggle is available to the user for this conversation.
605  optional OffTheRecordToggle otr_toggle = 11;
606  optional bool conversation_history_supported = 12;
607  repeated ParticipantId current_participant = 13;
608  repeated ConversationParticipantData participant_data = 14;
609  optional bool is_temporary = 15;
610  optional bool fork_on_external_invite = 16;
611  repeated NetworkType network_type = 18;
612  optional ForceHistory force_history_state = 19;
613  optional bool is_group_link_sharing_enabled = 21;
614  optional GroupLinkSharingStatus group_link_sharing_status = 22;
615}
616
617message EasterEgg {
618  optional string message = 1;
619}
620
621enum BlockState {
622  BLOCK_STATE_UNKNOWN = 0;
623  BLOCK_STATE_BLOCK = 1;
624  BLOCK_STATE_UNBLOCK = 2;
625}
626
627message BlockStateChange {
628  optional ParticipantId participant_id = 1;
629  optional BlockState new_block_state = 2;
630}
631
632message InvitationState {
633  optional uint64 unread_invite_count = 1;
634  optional uint64 latest_read_timestamp = 2;
635}
636
637enum ReplyToInviteType {
638  REPLY_TO_INVITE_TYPE_UNKNOWN = 0;
639  REPLY_TO_INVITE_TYPE_ACCEPT = 1;
640  REPLY_TO_INVITE_TYPE_DECLINE = 2;
641}
642
643message Photo {
644  // Picasa photo ID.
645  optional string photo_id = 1;
646  optional bool delete_albumless_source_photo = 2;
647  // Optional Picasa user ID needed for photos from other accounts (eg. stickers).
648  optional string user_id = 3;
649  optional bool reference_original_photo = 4;
650
651  // TODO: test delete_albumless_source_photo
652}
653
654message ExistingMedia {
655  optional Photo photo = 1;
656}
657
658message EventRequestHeader {
659  optional ConversationId conversation_id = 1;
660  optional uint64 client_generated_id = 2;
661  optional OffTheRecordStatus expected_otr = 3;
662  optional DeliveryMedium delivery_medium = 4;
663  optional EventType event_type = 5;
664}
665
666// Identifies the client.
667enum ClientId {
668  CLIENT_ID_UNKNOWN = 0;
669  // Hangouts app for Android.
670  CLIENT_ID_ANDROID = 1;
671  // Hangouts app for iOS.
672  CLIENT_ID_IOS = 2;
673  // Hangouts Chrome extension.
674  CLIENT_ID_CHROME = 3;  // AKA Quasar
675  //CLIENT_ID_WEB = 4;
676  // Hangouts web interface in Google Plus.
677  CLIENT_ID_WEB_GPLUS = 5;
678  // Hangouts web interface in Gmail.
679  CLIENT_ID_WEB_GMAIL = 6;
680  CLIENT_ID_BOT = 7;
681  //CLIENT_ID_WEB_VIDEO_CALL = 8;
682  CLIENT_ID_GLASS_SERVER = 9;
683  CLIENT_ID_PSTN_BOT = 10;
684  CLIENT_ID_TEE = 11;
685  //CLIENT_ID_WEB_BIGTOP = 12;
686  // Hangouts Chrome app ("ultraviolet").
687  CLIENT_ID_ULTRAVIOLET = 13;
688  CLIENT_ID_ROOM_SERVER = 14;
689  //CLIENT_ID_WEB_STANDALONE_APP = 15;
690  CLIENT_ID_SPEAKEASY = 16;
691  CLIENT_ID_GOOGLE_VOICE = 17;
692  CLIENT_ID_PROBER = 18;
693  //CLIENT_ID_EXTERNAL = 19;
694  //CLIENT_ID_BB_BOT = 23;
695  //CLIENT_ID_POWWOW = 24;
696  //CLIENT_ID_GPLUS_SERVER = 25;
697  //CLIENT_ID_HANGOUTS_PUSHER = 26;
698  CLIENT_ID_ANDROID_PSTN_ONLY = 27;
699  //CLIENT_ID_REALTIME_SUPPORT = 28;
700  //CLIENT_ID_CHAT_EXPUNGER = 29;
701  //CLIENT_ID_CAPTIONS_BOT = 30;
702  //CLIENT_ID_MESI = 31;
703  //CLIENT_ID_REALTIME_MEDIA_JS = 32;
704  //CLIENT_ID_WABEL_MEDIACALL = 33;
705  CLIENT_ID_EXPRESSLANE = 34;
706  CLIENT_ID_TEST_CLIENT = 35;
707  //CLIENT_ID_WEB_CONTACTS = 36;
708  //CLIENT_ID_WEB_CALLMEMAYBE = 37;
709  //CLIENT_ID_GMAIL = 38;
710  //CLIENT_ID_CASTOUTS = 39;
711  //CLIENT_ID_IRONMAN_WEB = 40;
712  //CLIENT_ID_IRONMAN_ANDROID = 41;
713  //CLIENT_ID_IRONMAN_IOS = 42;
714  //CLIENT_ID_ANONYMOUS_WEB_VIDEO_CALL = 43;
715  // Hangouts web app (https://hangouts.google.com).
716  CLIENT_ID_WEB_HANGOUTS = 44;
717  //CLIENT_ID_WEB_SHORTLINK = 45;
718  //CLIENT_ID_HOTLANE = 46;
719  //CLIENT_ID_IOS_SHARE = 47;
720  //CLIENT_ID_RIGEL = 48;
721  //CLIENT_ID_PORTHOLE = 49;
722  //CLIENT_ID_BOQ_EXPRESSLANE = 50;
723}
724
725// Build type of the client.
726enum ClientBuildType {
727  BUILD_TYPE_UNKNOWN = 0;
728  // Web app.
729  BUILD_TYPE_PRODUCTION_WEB = 1;
730  BUILD_TYPE_DOGFOOD = 2;
731  // Native app.
732  BUILD_TYPE_PRODUCTION_APP = 3;
733}
734
735// The client and device version.
736message ClientVersion {
737  // Identifies the client.
738  optional ClientId client_id = 1;
739  // The client build type.
740  optional ClientBuildType build_type = 2;
741  // Client version.
742  optional string major_version = 3;
743  // Client version timestamp.
744  optional uint64 version_timestamp = 4;
745  // OS version string (for native apps).
746  optional string device_os_version = 5;
747  // Device hardware name (for native apps).
748  optional string device_hardware = 6;
749}
750
751enum Device {
752  DEVICE_UNKNOWN = 0;
753  DEVICE_ANDROID_PHONE = 2;
754  DEVICE_ANDROID_TABLET = 3;
755  DEVICE_IOS_PHONE = 4;
756  DEVICE_IOS_TABLET = 5;
757}
758
759enum Application {
760  APPLICATION_BABEL = 407;
761}
762
763enum Platform {
764  PLATFORM_UNKNOWN = 0;
765  PLATFORM_NATIVE = 2;
766}
767
768message RtcClient {
769  optional Device device = 1;
770  optional Application application = 2;
771  optional Platform platform = 3;
772}
773
774// Header for requests from the client to the server.
775message RequestHeader {
776  optional ClientVersion client_version = 1;
777  optional ClientIdentifier client_identifier = 2;
778  optional string language_code = 4;
779  optional bool include_updated_conversation = 5;
780  optional uint32 retry_attempt = 6;
781
782  // TODO: incomplete
783  //optional uint64 message_id = 3;
784  //optional ClientInstrumentationInfo client_instrumentation_info = 3;
785  optional RtcClient rtc_client = 7;
786  //optional string client_generated_request_id = 8;
787}
788
789// Status of the response from the server to the client.
790enum ResponseStatus {
791  RESPONSE_STATUS_UNKNOWN = 0;
792  RESPONSE_STATUS_OK = 1;
793  RESPONSE_STATUS_BUSY = 2;
794  RESPONSE_STATUS_UNEXPECTED_ERROR = 3;
795  RESPONSE_STATUS_INVALID_REQUEST = 4;
796  RESPONSE_STATUS_ERROR_RETRY_LIMIT = 5;
797  RESPONSE_STATUS_ERROR_FORWARDED = 6;
798  RESPONSE_STATUS_ERROR_QUOTA_EXCEEDED = 7;
799  RESPONSE_STATUS_ERROR_INVALID_CONVERSATION = 8;
800  RESPONSE_STATUS_ERROR_VERSION_MISMATCH = 9;
801  RESPONSE_STATUS_ERROR_ACCESS_CHECK_FAILED = 10;
802  RESPONSE_STATUS_ERROR_NOT_FOUND = 11;
803}
804
805// Header for responses from the server to the client.
806message ResponseHeader {
807  optional ResponseStatus status = 1;
808  optional string error_description = 2;
809  optional string debug_url = 3;
810  optional string request_trace_id = 4;
811  optional uint64 current_server_time = 5;
812  optional uint64 backoff_duration_millis = 6;
813  //optional string client_generated_request_id = 7;
814  optional string localized_user_visible_error_message = 8;
815  //optional string build_label = 10;
816  //optional int32 changelist_number = 11;
817}
818
819// A user that can participate in conversations.
820message Entity {
821  // The user's ID.
822  optional ParticipantId id = 9;
823  // Optional user presence status.
824  optional Presence presence = 8;
825  optional bool invalid = 7;
826  //optional Availability availability = 5;
827  // Optional user properties.
828  optional EntityProperties properties = 10;
829  optional bool blocked = 11;
830  //optional DomainProperties domain_properties = 12;
831  optional ParticipantType entity_type = 13;
832  //optional bool is_babel_user = 14;
833  //optional BabelUserState babel_user_state = 15;
834  enum PastHangoutState {
835    PAST_HANGOUT_STATE_UNKNOWN = 0;
836    PAST_HANGOUT_STATE_HAD_PAST_HANGOUT = 1;
837    PAST_HANGOUT_STATE_NO_PAST_HANGOUT = 2;
838  }
839  optional PastHangoutState had_past_hangout_state = 16;
840  //optional InvitationStatus invitation_status = 17;
841  //optional bool is_anonymous_phone = 18;
842}
843
844message EntityProperties {
845  optional ProfileType type = 1;
846  optional string display_name = 2;
847  optional string first_name = 3;
848  // Photo URL with protocol scheme omitted (eg.
849  // "//lh.googleusercontent.com/...").
850  optional string photo_url = 4;
851  repeated string email = 5;
852  repeated string phone = 6;
853  optional string location = 7;
854  optional string organization = 8;
855  optional string role = 9;
856  optional bool in_users_domain = 10;
857  optional Gender gender = 11;
858  optional PhotoUrlStatus photo_url_status = 12;
859  //repeated string circle_id_array = 13;
860  //repeated ContactPhoneNumber phone_number_array = 14;
861  optional string canonical_email = 15;
862  //repeated ClientAffinity affinity_array = 16;
863}
864
865// Status of EntityProperties.photo_url.
866enum PhotoUrlStatus {
867  PHOTO_URL_STATUS_UNKNOWN = 0;
868  // URL is a placeholder.
869  PHOTO_URL_STATUS_PLACEHOLDER = 1;
870  // URL is a photo set by the user.
871  PHOTO_URL_STATUS_USER_PHOTO = 2;
872}
873
874enum Gender {
875  GENDER_UNKNOWN = 0;
876  GENDER_MALE = 1;
877  GENDER_FEMALE = 2;
878}
879
880enum ProfileType {
881  PROFILE_TYPE_NONE = 0;
882  PROFILE_TYPE_ES_USER = 1;
883  PROFILE_TYPE_PAGE = 2;
884}
885
886// State of a conversation and recent events.
887message ConversationState {
888  optional ConversationId conversation_id = 1;
889  optional Conversation conversation = 2;
890  repeated Event event = 3;
891  //optional bool must_query_separately = 4;
892  optional EventContinuationToken event_continuation_token = 5;
893  //optional uint64 leave_timestamp = 6;
894  //repeated DeleteAction delete_action_array = 7;
895  //optional EventContinuationToken forward_continuation_token = 8;
896}
897
898// Token that allows retrieving more events from a position in a conversation.
899// Specifying event_timestamp is sufficient.
900message EventContinuationToken {
901  optional string event_id = 1;
902  optional bytes storage_continuation_token = 2;
903  optional uint64 event_timestamp = 3;
904}
905
906// Specifies an entity to lookup by one of its properties.
907message EntityLookupSpec {
908  optional string gaia_id = 1;
909  optional string jid = 2;
910  optional string email = 3;
911  optional string phone = 4;
912  optional string chat_id = 5;
913  // Whether create a gaia_id for off-network contacts (eg. Google Voice contacts).
914  optional bool create_offnetwork_gaia = 6;
915}
916
917// A type of binary configuration option.
918enum ConfigurationBitType {
919
920  // TODO
921  // HANGOUT_P2P_NOTICE_ACKNOWLEDGED
922
923  CONFIGURATION_BIT_TYPE_UNKNOWN = 0;
924  CONFIGURATION_BIT_TYPE_QUASAR_MARKETING_PROMO_DISMISSED = 1;
925  CONFIGURATION_BIT_TYPE_GPLUS_SIGNUP_PROMO_DISMISSED = 2;
926  CONFIGURATION_BIT_TYPE_CHAT_WITH_CIRCLES_ACCEPTED = 3;
927  CONFIGURATION_BIT_TYPE_CHAT_WITH_CIRCLES_PROMO_DISMISSED = 4;
928  CONFIGURATION_BIT_TYPE_ALLOWED_FOR_DOMAIN = 5;
929  CONFIGURATION_BIT_TYPE_GMAIL_CHAT_ARCHIVE_ENABLED = 6;
930  CONFIGURATION_BIT_TYPE_GPLUS_UPGRADE_ALLOWED_FOR_DOMAIN = 7;
931  CONFIGURATION_BIT_TYPE_RICH_PRESENCE_ACTIVITY_PROMO_SHOWN = 8;
932  CONFIGURATION_BIT_TYPE_RICH_PRESENCE_DEVICE_PROMO_SHOWN = 9;
933  CONFIGURATION_BIT_TYPE_RICH_PRESENCE_IN_CALL_STATE_PROMO_SHOWN = 10;
934  CONFIGURATION_BIT_TYPE_RICH_PRESENCE_MOOD_PROMO_SHOWN = 11;
935  CONFIGURATION_BIT_TYPE_CAN_OPT_INTO_GV_SMS_INTEGRATION = 12;
936  CONFIGURATION_BIT_TYPE_GV_SMS_INTEGRATION_ENABLED = 13;
937  CONFIGURATION_BIT_TYPE_GV_SMS_INTEGRATION_PROMO_SHOWN = 14;
938  CONFIGURATION_BIT_TYPE_BUSINESS_FEATURES_ELIGIBLE = 15;
939  CONFIGURATION_BIT_TYPE_BUSINESS_FEATURES_PROMO_DISMISSED = 16;
940  CONFIGURATION_BIT_TYPE_BUSINESS_FEATURES_ENABLED = 17;
941  CONFIGURATION_BIT_TYPE_UNKNOWN_18 = 18;
942  CONFIGURATION_BIT_TYPE_RICH_PRESENCE_LAST_SEEN_MOBILE_PROMO_SHOWN = 19;
943  CONFIGURATION_BIT_TYPE_RICH_PRESENCE_LAST_SEEN_DESKTOP_PROMPT_SHOWN = 20;
944  CONFIGURATION_BIT_TYPE_RICH_PRESENCE_LAST_SEEN_MOBILE_PROMPT_SHOWN = 21;
945  CONFIGURATION_BIT_TYPE_RICH_PRESENCE_LAST_SEEN_DESKTOP_PROMO_SHOWN = 22;
946  CONFIGURATION_BIT_TYPE_CONVERSATION_INVITE_SETTINGS_SET_TO_CUSTOM = 23;
947  CONFIGURATION_BIT_TYPE_REPORT_ABUSE_NOTICE_ACKNOWLEDGED = 24;
948  CONFIGURATION_BIT_TYPE_UNICORN_USE_CHILD_PRODUCT = 25;
949  CONFIGURATION_BIT_TYPE_UNICORN_FULLY_DISABLED_BY_PARENT = 26;
950  CONFIGURATION_BIT_TYPE_PHONE_VERIFICATION_MOBILE_PROMPT_SHOWN = 27;
951  CONFIGURATION_BIT_TYPE_CAN_USE_GV_CALLER_ID_FEATURE = 28;
952  CONFIGURATION_BIT_TYPE_PHOTO_SERVICE_REGISTERED = 29;
953  CONFIGURATION_BIT_TYPE_GV_CALLER_ID_WABEL_FIRST_TIME_DIALOG_SHOWN = 30;
954  CONFIGURATION_BIT_TYPE_HANGOUT_P2P_NOTICE_NEEDS_ACKNOWLEDGEMENT = 31;
955  CONFIGURATION_BIT_TYPE_HANGOUT_P2P_ENABLED = 32;
956  CONFIGURATION_BIT_TYPE_INVITE_NOTIFICATIONS_ENABLED = 33;
957  CONFIGURATION_BIT_TYPE_DESKTOP_AUTO_EMOJI_CONVERSION_ENABLED = 34;
958  CONFIGURATION_BIT_TYPE_WARM_WELCOME_SEEN = 35;
959  CONFIGURATION_BIT_TYPE_INVITE_HAPPY_STATE_PROMO_SEEN = 36;
960  CONFIGURATION_BIT_TYPE_DESKTOP_HOST_DENSITY_SETTINGS_ENABLED = 37;
961  CONFIGURATION_BIT_TYPE_DESKTOP_COMPACT_MODE_ENABLED = 38;
962}
963
964message ConfigurationBit {
965  optional ConfigurationBitType configuration_bit_type = 1;
966  optional bool value = 2;
967}
968
969enum RichPresenceType {
970  RICH_PRESENCE_TYPE_UNKNOWN = 0;
971  RICH_PRESENCE_TYPE_IN_CALL_STATE = 1;
972  RICH_PRESENCE_TYPE_DEVICE = 2;
973  RICH_PRESENCE_TYPE_MOOD = 3;
974  RICH_PRESENCE_TYPE_ACTIVITY = 4;
975  RICH_PRESENCE_TYPE_GLOBALLY_ENABLED = 5;
976  RICH_PRESENCE_TYPE_LAST_SEEN = 6;
977}
978
979message RichPresenceState {
980  repeated RichPresenceEnabledState get_rich_presence_enabled_state = 3;
981}
982
983message RichPresenceEnabledState {
984  optional RichPresenceType type = 1;
985  optional bool enabled = 2;
986}
987
988enum FieldMask {
989  FIELD_MASK_REACHABLE = 1;
990  FIELD_MASK_AVAILABLE = 2;
991  FIELD_MASK_MOOD = 3;
992  FIELD_MASK_LOCATION = 4;
993  FIELD_MASK_IN_CALL = 6;
994  FIELD_MASK_DEVICE = 7;
995  FIELD_MASK_LAST_SEEN = 10;
996
997  // TODO: 5,8,9?
998  //5 - mood, 3 is statusmessage
999  //8 - activity
1000  //9 - calendarpresence
1001}
1002
1003message DesktopOffSetting {
1004  // State of "desktop off" setting.
1005  optional bool desktop_off = 1;
1006}
1007
1008message DesktopOffState {
1009  // Whether Hangouts desktop is signed off or on.
1010  optional bool desktop_off = 1;
1011  optional uint64 version = 2;
1012}
1013
1014// Enable or disable do-not-disturb mode. Not to be confused with
1015// DoNotDisturbSetting, which is used to indicate the state of do-not-disturb
1016// mode.
1017message DndSetting {
1018  // Whether to enable or disable do-not-disturb mode.
1019  optional bool do_not_disturb = 1;
1020  // Do not disturb expiration in seconds.
1021  optional uint64 timeout_secs = 2;
1022}
1023
1024message PresenceStateSetting {
1025  optional uint64 timeout_secs = 1;
1026  optional ClientPresenceStateType type = 2;
1027}
1028
1029message MoodMessage {
1030  optional MoodContent mood_content = 1;
1031}
1032
1033message MoodContent {
1034  repeated Segment segment = 1;
1035}
1036
1037// The user's mood message.
1038message MoodSetting {
1039  optional MoodMessage mood_message = 1;
1040}
1041
1042message MoodState {
1043  //repeated InCallState in_call_array = 2;
1044  //repeated RichPresenceEnabledState rich_presence_enabled = 3;
1045  optional MoodSetting mood_setting = 4;
1046}
1047
1048enum DeleteType {
1049  DELETE_TYPE_UNKNOWN = 0;
1050  DELETE_TYPE_UPPER_BOUND = 1;
1051  DELETE_TYPE_PER_EVENT = 2;
1052}
1053
1054message DeleteAction {
1055  optional uint64 delete_action_timestamp = 1;
1056  optional uint64 delete_upper_bound_timestamp = 2;
1057  optional DeleteType delete_type = 3;
1058}
1059
1060message InviteeID {
1061  optional string gaia_id = 1;
1062  optional string circle_id = 2;
1063  optional string chat_id = 3;
1064  optional string fallback_name = 4;
1065}
1066
1067enum SyncFilter {
1068  SYNC_FILTER_UNKNOWN = 0;
1069  SYNC_FILTER_INBOX = 1;
1070  SYNC_FILTER_ARCHIVED = 2;
1071  SYNC_FILTER_ACTIVE = 3;
1072  SYNC_FILTER_INVITED = 4;
1073  SYNC_FILTER_INVITED_LOW_AFFINITY = 5;
1074}
1075
1076// Describes a user's country.
1077message Country {
1078  // Abbreviated region code (eg. "CA").
1079  optional string region_code = 1;
1080  // Country's calling code (eg. "1").
1081  optional uint64 country_code = 2;
1082}
1083
1084enum SoundState {
1085  SOUND_STATE_UNKNOWN = 0;
1086  SOUND_STATE_ON = 1;
1087  SOUND_STATE_OFF = 2;
1088}
1089
1090// Sound settings in the desktop Hangouts client.
1091message DesktopSoundSetting {
1092  // Whether to play sound for incoming messages.
1093  optional SoundState desktop_sound_state = 1;
1094  // Whether to ring for incoming calls.
1095  optional SoundState desktop_ring_sound_state = 2;
1096}
1097
1098enum CallerIdSettingsMask {
1099  CALLER_ID_SETTINGS_MASK_UNKNOWN = 0;
1100  CALLER_ID_SETTINGS_MASK_PROVIDED = 1;
1101}
1102
1103message PhoneData {
1104  repeated Phone phone = 1;
1105  //repeated CallerIdSetting caller_id_setting = 2;
1106  optional CallerIdSettingsMask caller_id_settings_mask = 3;
1107}
1108
1109enum PhoneVerificationStatus {
1110  PHONE_VERIFICATION_STATUS_UNKNOWN = 0;
1111  PHONE_VERIFICATION_STATUS_VERIFIED = 1;
1112}
1113
1114enum PhoneDiscoverabilityStatus {
1115  PHONE_DISCOVERABILITY_STATUS_UNKNOWN = 0;
1116  PHONE_DISCOVERABILITY_STATUS_OPTED_IN_AND_DISCOVERABLE = 1;
1117  PHONE_DISCOVERABILITY_STATUS_OPTED_IN_BUT_NOT_DISCOVERABLE = 2;
1118  PHONE_DISCOVERABILITY_STATUS_OPTED_OUT = 3;
1119}
1120
1121message Phone {
1122  optional PhoneNumber phone_number = 1;
1123  optional bool google_voice = 2;
1124  optional PhoneVerificationStatus verification_status = 3;
1125  optional bool discoverable = 4;
1126  optional PhoneDiscoverabilityStatus discoverability_status = 5;
1127  optional bool primary = 6;
1128}
1129
1130enum PhoneValidationResult {
1131  PHONE_VALIDATION_RESULT_IS_POSSIBLE = 0;
1132}
1133
1134message I18nData {
1135  optional string national_number = 1;
1136  optional string international_number = 2;
1137  optional uint64 country_code = 3;
1138  optional string region_code = 4;
1139  optional bool is_valid = 5;
1140  optional PhoneValidationResult validation_result = 6;
1141}
1142
1143message PhoneNumber {
1144  // Phone number as string (eg. "+15551234567").
1145  optional string e164 = 1;
1146  optional I18nData i18n_data = 2;
1147}
1148
1149message SuggestedContactGroupHash {
1150  // Number of results to return from this group.
1151  optional uint64 max_results = 1;
1152  // An optional 4-byte hash. If this matches the server's hash, no results
1153  // will be sent.
1154  optional bytes hash = 2;
1155}
1156
1157message SuggestedContact {
1158  // The contact's entity.
1159  optional Entity entity = 1;
1160  // The contact's invitation status.
1161  optional InvitationStatus invitation_status = 2;
1162}
1163
1164message SuggestedContactGroup {
1165  // True if the request's hash matched and no contacts will be included.
1166  optional bool hash_matched = 1;
1167  // A 4-byte hash which can be used in subsequent requests.
1168  optional bytes hash = 2;
1169  // List of contacts in this group.
1170  repeated SuggestedContact contact = 3;
1171}
1172
1173// ----------------------------------------------------------------------------
1174// State Update and Notifications
1175// ----------------------------------------------------------------------------
1176
1177// Pushed from the server to the client to notify it of state changes. Includes
1178// exactly one type of notification, and optionally updates the attributes of a
1179// conversation.
1180message StateUpdate {
1181
1182  optional StateUpdateHeader state_update_header = 1;
1183
1184  // If set, includes conversation attributes that have been updated by the
1185  // notification.
1186  optional Conversation conversation = 13;
1187
1188  //TODO implement in pblite handler
1189  //oneof state_update {
1190
1191  optional  ConversationNotification conversation_notification = 2;
1192  optional  EventNotification event_notification = 3;
1193  optional  SetFocusNotification focus_notification = 4;
1194  optional  SetTypingNotification typing_notification = 5;
1195  optional  SetConversationNotificationLevelNotification notification_level_notification = 6;
1196  optional  ReplyToInviteNotification reply_to_invite_notification = 7;
1197  optional  WatermarkNotification watermark_notification = 8;
1198
1199  // optional  //UnimplementedMessage unknown_1 = 9;
1200  // optional  //UnimplementedMessage settings_notification = 10;
1201    // TODO: rename to ViewModificationNotification?
1202
1203
1204  optional  ConversationViewModification view_modification = 11;
1205  optional  EasterEggNotification easter_egg_notification = 12;
1206  optional  SelfPresenceNotification self_presence_notification = 14;
1207  optional  DeleteActionNotification delete_notification = 15;
1208  optional  PresenceNotification presence_notification = 16;
1209  optional  BlockNotification block_notification = 17;
1210
1211  // optional  InvitationWartermarkNotification invitation_watermark_notification = 18;
1212
1213  optional  SetNotificationSettingNotification notification_setting_notification = 19;
1214  optional  RichPresenceEnabledStateNotification rich_presence_enabled_state_notification = 20;
1215
1216  //optional ContactsNotification contacts_notification = 21;
1217  //optional ConversationDeliveryMediumModification delivery_medium_modification = 23;
1218  //optional CallerIdConfigNotification caller_id_config_notification = 28;
1219  //optional  EventSeenNotification event_seen_notification = 30;
1220  //}
1221  //optional GlobalNotificationLevelNotification global_notification_level_notification = 31;
1222}
1223
1224// Header for StateUpdate messages.
1225message StateUpdateHeader {
1226  optional ActiveClientState active_client_state = 1;
1227  optional string request_trace_id = 3;
1228  optional NotificationSettings notification_settings = 4;
1229  optional uint64 current_server_time = 5;
1230
1231  // TODO:
1232  // optional UserSettings self_settings (dnd_state) = 2;
1233  // optional ArchiveSettings archive_settings (is_babel_user) = 6
1234  // optional string client_generated_request_id = 7;
1235  // optional ID of the client causing the update
1236  // optional string self_fanout_id = 8;
1237}
1238
1239// List of StateUpdate messages to allow pushing multiple notifications from
1240// the server to the client simultaneously.
1241message BatchUpdate {
1242  repeated StateUpdate state_update = 1;
1243}
1244
1245message ConversationNotification {
1246  optional Conversation conversation = 1;
1247}
1248
1249message EventNotification {
1250  optional Event event = 1;
1251}
1252
1253message SetFocusNotification {
1254  optional ConversationId conversation_id = 1;
1255  optional ParticipantId sender_id = 2;
1256  optional uint64 timestamp = 3;
1257  optional FocusType type = 4;
1258  //optional FocusDevice device = 5;
1259  //optional uint32 timeout_secs = 5;
1260}
1261
1262message SetTypingNotification {
1263  optional ConversationId conversation_id = 1;
1264  optional ParticipantId sender_id = 2;
1265  optional uint64 timestamp = 3;
1266  optional TypingType type = 4;
1267}
1268
1269message SetConversationNotificationLevelNotification {
1270  optional ConversationId conversation_id = 1;
1271  optional NotificationLevel level = 2;
1272  optional uint32 revert_timeout_secs = 3;
1273  optional uint64 timestamp = 4;
1274}
1275
1276message ReplyToInviteNotification {
1277  optional ConversationId conversation_id = 1;
1278  optional ReplyToInviteType type = 2;
1279
1280  // TODO: untested
1281}
1282
1283message WatermarkNotification {
1284  optional ParticipantId sender_id = 1;
1285  optional ConversationId conversation_id = 2;
1286  optional uint64 latest_read_timestamp = 3;
1287}
1288
1289message ConversationViewModification {
1290  optional ConversationId conversation_id = 1;
1291  optional ConversationView old_view = 2;
1292  optional ConversationView new_view = 3;
1293}
1294
1295message GroupLinkSharingModification {
1296  optional GroupLinkSharingStatus new_status = 1;
1297}
1298
1299message EasterEggNotification {
1300  optional ParticipantId sender_id = 1;
1301  optional ConversationId conversation_id = 2;
1302  optional EasterEgg easter_egg = 3;
1303}
1304
1305// Notifies the status of other clients and mood.
1306message SelfPresenceNotification {
1307  optional ClientPresenceState client_presence_state = 1;
1308  //optional ClientPresence presence = 2;
1309  optional DoNotDisturbSetting do_not_disturb_setting = 3;
1310  optional DesktopOffSetting desktop_off_setting = 4;
1311  optional DesktopOffState desktop_off_state = 5;
1312  optional MoodState mood_state = 6;
1313}
1314
1315message DeleteActionNotification {
1316  optional ConversationId conversation_id = 1;
1317  optional DeleteAction delete_action = 2;
1318}
1319
1320message PresenceNotification {
1321  repeated PresenceResult presence = 1;
1322}
1323
1324message BlockNotification {
1325  repeated BlockStateChange block_state_change = 1;
1326}
1327
1328message InvitationWatermarkNotification {
1329  optional InvitationState state = 1;
1330}
1331
1332message SetNotificationSettingNotification {
1333  repeated ConfigurationBit configuration_bit = 1;
1334  optional DesktopSoundSetting desktop_sound_setting = 2;
1335}
1336
1337message RichPresenceEnabledStateNotification {
1338  repeated RichPresenceEnabledState rich_presence_enabled_state = 1;
1339}
1340
1341message ConversationSpec {
1342  optional ConversationId conversation_id = 1;
1343  optional ParticipantId participant_id = 2;
1344  optional InviteeID invitee_id = 3;
1345}
1346
1347// message ConversationEventSeenNotification {
1348  // repeated ConversationEventsSeen conversation_events = 1;
1349// }
1350
1351// message ConversationEventsSeen {
1352  // optional ConversationId conversation_id = 1;
1353  // repeated EventSeen event_seen = 2;
1354// }
1355
1356// message EventSeen {
1357  // optional string event_id = 1;
1358  // optional uint64 event_timestamp = 2;
1359  // optional uint64 unknown_type = 3;
1360// }
1361
1362enum OffnetworkAddressType {
1363  OFFNETWORK_ADDRESS_TYPE_UNKNOWN = 0; //PHONE
1364  OFFNETWORK_ADDRESS_TYPE_EMAIL = 1;
1365}
1366
1367message OffnetworkAddress {
1368  optional OffnetworkAddressType type = 1;
1369  //optional string phone = 2;
1370  optional string email = 3;
1371}
1372
1373enum GroupLinkSharingStatus {
1374  GROUP_LINK_SHARING_STATUS_UNKNOWN = 0;
1375  GROUP_LINK_SHARING_STATUS_ON = 1;
1376  GROUP_LINK_SHARING_STATUS_OFF = 2;
1377  GROUP_LINK_SHARING_STATUS_NOT_AVAILABLE = 3;
1378}
1379
1380// ----------------------------------------------------------------------------
1381// Requests & Responses
1382// ----------------------------------------------------------------------------
1383
1384message AddUserRequest {
1385  optional RequestHeader request_header = 1;
1386  repeated InviteeID invitee_id = 3;
1387  optional EventRequestHeader event_request_header = 5;
1388}
1389
1390message AddUserResponse {
1391  optional ResponseHeader response_header = 1;
1392  optional Event created_event = 5;
1393
1394  //repeated InviteeError invitee_error = 2;
1395  //optional Conversation updated_conversation = 6;
1396}
1397
1398message CreateConversationRequest {
1399  optional RequestHeader request_header = 1;
1400  optional ConversationType type = 2;
1401  optional uint64 client_generated_id = 3;
1402  optional string name = 4;
1403  repeated InviteeID invitee_id = 5;
1404
1405  //optional DeliveryMedium delivery_medium = 11;
1406  //optional InviteToken invite_token = 12;
1407  //optional string conversation_avatar_media_key = 14;
1408}
1409
1410message CreateConversationResponse {
1411  optional ResponseHeader response_header = 1;
1412  optional Conversation conversation = 2;
1413  optional bool new_conversation_created = 7;
1414
1415  //repeated InviteeError invitee_error = 3;
1416}
1417
1418message DeleteConversationRequest {
1419  optional RequestHeader request_header = 1;
1420  optional ConversationId conversation_id = 2;
1421  optional uint64 delete_upper_bound_timestamp = 3;
1422}
1423
1424message DeleteConversationResponse {
1425  optional ResponseHeader response_header = 1;
1426  optional DeleteAction delete_action = 2;
1427}
1428
1429message EasterEggRequest {
1430  optional RequestHeader request_header = 1;
1431  optional ConversationId conversation_id = 2;
1432  optional EasterEgg easter_egg = 3;
1433}
1434
1435message EasterEggResponse {
1436  optional ResponseHeader response_header = 1;
1437  optional uint64 timestamp = 2;
1438}
1439
1440message GetConversationRequest {
1441  optional RequestHeader request_header = 1;
1442  optional ConversationSpec conversation_spec = 2;
1443  optional bool include_conversation_metadata = 3;
1444  optional bool include_event = 4;
1445  optional uint64 max_events_per_conversation = 6;
1446  optional EventContinuationToken event_continuation_token = 7;
1447  optional bool include_presence = 8;
1448
1449  // TODO:
1450  // unknown = 5;
1451  //optional EventContinuationToken forward_continuation_token = 11;
1452}
1453
1454message GetConversationResponse {
1455  optional ResponseHeader response_header = 1;
1456  optional ConversationState conversation_state = 2;
1457  //optional GetConversationError error = 3;
1458  optional PresenceResult presence = 4;
1459}
1460
1461message GetEntityByIdRequest {
1462  optional RequestHeader request_header = 1;
1463  optional EntityLookupSpec lookup_spec = 2;
1464  repeated EntityLookupSpec batch_lookup_spec = 3;
1465  repeated FieldMask field_mask = 4;
1466}
1467
1468message GetEntityByIdResponse {
1469  optional ResponseHeader response_header = 1;
1470  // Resulting entities of PARTICIPANT_TYPE_GAIA only.
1471  repeated Entity entity = 2;
1472  // All resulting entities.
1473  repeated EntityResult entity_result = 3;
1474}
1475
1476message EntityResult {
1477  optional EntityLookupSpec lookup_spec = 1;
1478  repeated Entity entity = 2;
1479}
1480
1481message GetGroupConversationUrlRequest {
1482  optional RequestHeader request_header = 1;
1483  optional ConversationId conversation_id = 2;
1484}
1485
1486message GetGroupConversationUrlResponse {
1487  optional ResponseHeader response_header = 1;
1488  // URL for others to join the conversation.
1489  optional string group_conversation_url = 2;
1490}
1491
1492message GetSuggestedEntitiesRequest {
1493  optional RequestHeader request_header = 1;
1494  // Max number of non-grouped entities to return.
1495  optional uint64 max_count = 4;
1496  // Optional hash for "favorites" contact group.
1497  optional SuggestedContactGroupHash favorites = 8;
1498  // Optional hash for "contacts you hangout with" contact group.
1499  optional SuggestedContactGroupHash contacts_you_hangout_with = 9;
1500  // Optional hash for "other contacts on hangouts" contact group.
1501  optional SuggestedContactGroupHash other_contacts_on_hangouts = 10;
1502  // Optional hash for "other contacts" contact group.
1503  optional SuggestedContactGroupHash other_contacts = 11;
1504  // Optional hash for "dismissed contacts" contact group.
1505  optional SuggestedContactGroupHash dismissed_contacts = 12;
1506  // Optional hash for "pinned favorites" contact group.
1507  optional SuggestedContactGroupHash pinned_favorites = 13;
1508
1509  // TODO: possible other fields:
1510  // repeated EntityID given_entity_id = 2
1511  // repeated EntityFilterType entity_type_filter = 3;
1512  // optional bool include_availability = 5;
1513  // repeated ParticipantId given_entity_id = 6
1514  // optional bool include_legacy = 7;
1515  // optional bool include_is_babel_user = 14;
1516  // repeated int additional_entity_data = 15;
1517}
1518
1519message GetSuggestedEntitiesResponse {
1520  optional ResponseHeader response_header = 1;
1521  repeated Entity entity = 2;
1522  //optional bool scoring_failed = 3;
1523  optional SuggestedContactGroup favorites = 4;
1524  optional SuggestedContactGroup contacts_you_hangout_with = 5;
1525  optional SuggestedContactGroup other_contacts_on_hangouts = 6;
1526  optional SuggestedContactGroup other_contacts = 7;
1527  optional SuggestedContactGroup dismissed_contacts = 8;
1528  optional SuggestedContactGroup pinned_favorites = 9;
1529}
1530
1531message GetSelfInfoRequest {
1532  optional RequestHeader request_header = 1;
1533
1534  // TODO
1535  // repeated ClientRequestedFieldMask required_fields = 2;
1536  // repeated ClientRequestedFieldMask optional_fields = 3;
1537  // optional bool upgrade_to_babel = 4;
1538}
1539
1540message GetSelfInfoResponse {
1541  optional ResponseHeader response_header = 1;
1542  optional Entity self_entity = 2;
1543  optional bool is_known_minor = 3;
1544  repeated ClientPresenceState client_presence = 4;
1545  optional DoNotDisturbSetting dnd_state = 5;
1546  optional DesktopOffSetting desktop_off_setting = 6;
1547  optional PhoneData phone_data = 7;
1548  repeated ConfigurationBit configuration_bit = 8;
1549  optional DesktopOffState desktop_off_state = 9;
1550  optional bool google_plus_user = 10;
1551  optional DesktopSoundSetting desktop_sound_setting = 11;
1552  optional RichPresenceState rich_presence_state = 12;
1553  optional Country default_country = 19;
1554
1555  // TODO:
1556  // optional bool babel_user = 13;
1557  // optional bool desktop_availability_sharing_enabled = 14;
1558  // enum desktop_html5_notification_state? = 16;
1559  // optional bool google_plus_mobile_user = 15;
1560  // repeated ParticipantId managed_plus_page = 17;
1561  // optional AccountAgeGroup account_age_group = 18;
1562  // repeated ExperimentValue mobile_experiment = 20;
1563  // unknown = 22;
1564  // optional NotificationLevel default_notification_level = 24;
1565}
1566
1567message ModifyConversationViewRequest {
1568  optional RequestHeader request_header = 1;
1569  optional ConversationId conversation_id = 2;
1570  optional ConversationView new_view = 3;
1571  optional uint64 last_event_timestamp = 4;
1572}
1573
1574message ModifyConversationViewResponse {
1575  optional ResponseHeader response_header = 1;
1576}
1577
1578message OpenGroupConversationFromUrlRequest {
1579  optional RequestHeader request_header = 1;
1580  // optional EventRequestHeader event_request_header = 2;
1581  optional string url = 3;
1582}
1583
1584message OpenGroupConversationFromUrlResponse {
1585  optional ResponseHeader response_header = 1;
1586  optional ConversationId conversation_id = 2;
1587}
1588
1589message QueryPresenceRequest {
1590  optional RequestHeader request_header = 1;
1591  repeated ParticipantId participant_id = 2;
1592  repeated FieldMask field_mask = 3;
1593}
1594
1595message QueryPresenceResponse {
1596  optional ResponseHeader response_header = 1;
1597  repeated PresenceResult presence_result = 2;
1598}
1599
1600message RemoveUserRequest {
1601  optional RequestHeader request_header = 1;
1602  optional ConversationId conversation_id = 2;
1603  optional ParticipantId participant_id = 3;
1604  optional uint64 client_generated_id = 4;
1605  optional EventRequestHeader event_request_header = 5;
1606}
1607
1608message RemoveUserResponse {
1609  optional ResponseHeader response_header = 1;
1610  optional uint64 timestamp = 2;
1611  optional string event_id = 3;
1612  optional Event created_event = 4;
1613  optional Conversation updated_conversation = 5;
1614}
1615
1616message RenameConversationRequest {
1617  optional RequestHeader request_header = 1;
1618  optional ConversationId conversation_id = 2;
1619  optional string new_name = 3;
1620  optional uint64 client_generated_id = 4;
1621  optional EventRequestHeader event_request_header = 5;
1622}
1623
1624message RenameConversationResponse {
1625  optional ResponseHeader response_header = 1;
1626  optional uint64 timestamp = 2;
1627  optional string event_id = 3;
1628  optional Event created_event = 4;
1629  optional Conversation updated_conversation = 5;
1630}
1631
1632message SearchEntitiesRequest {
1633  optional RequestHeader request_header = 1;
1634  optional string query = 3;
1635  optional uint64 max_count = 4;
1636
1637  // optional bool include_pages = 6;
1638  // optional bool include_is_babel_user = 7;
1639  // repeated AdditionalEntityData additional_entity_data = 8;
1640  // optional int32 max_conversation_count = 9;
1641}
1642
1643message SearchEntitiesResponse {
1644  optional ResponseHeader response_header = 1;
1645  repeated Entity entity = 2;
1646}
1647
1648message SendChatMessageRequest {
1649  optional RequestHeader request_header = 1;
1650  optional ConversationId conversation_id = 2;
1651  optional uint64 client_generated_id = 3;
1652  repeated EventAnnotation annotation = 5;
1653  optional MessageContent message_content = 6;
1654  optional ExistingMedia existing_media = 7;
1655  optional EventRequestHeader event_request_header = 8;
1656  optional InviteeID other_invitee_id = 9;
1657  //optional LocationSpec attach_location = 10;
1658  //optional ExternalImageSpec external_image_spec = 11;
1659  //repeated ChatMessageSpec chat_message_spec = 12;
1660}
1661
1662message SendChatMessageResponse {
1663  optional ResponseHeader response_header = 1;
1664  optional uint64 timestamp = 2;
1665  optional string event_id = 3;
1666  //repeated MediaUploadInfo media_upload_info = 4;
1667  //optional EventHeader event_header = 5;
1668  optional Event created_event = 6;
1669  optional Conversation updated_conversation = 7;
1670}
1671
1672message ModifyOTRStatusRequest {
1673  optional RequestHeader request_header = 1;
1674  optional OffTheRecordStatus otr_status = 3;
1675  optional EventRequestHeader event_request_header = 5;
1676}
1677
1678message ModifyOTRStatusResponse {
1679  optional ResponseHeader response_header = 1;
1680  optional Event created_event = 4;
1681  //optional Conversation updated_conversation = 5;
1682  //optional bool otr_unmodified = 6;
1683}
1684
1685message SendOffnetworkInvitationRequest {
1686  optional RequestHeader request_header = 1;
1687  optional OffnetworkAddress invitee_address = 2;
1688}
1689
1690message SendOffnetworkInvitationResponse {
1691  optional ResponseHeader response_header = 1;
1692  //optional OffnetworkInvitationError error = 2;
1693}
1694
1695message SetActiveClientRequest {
1696  optional RequestHeader request_header = 1;
1697  // Whether to set the client as active or inactive.
1698  optional bool is_active = 2;
1699  // 'email/resource'.
1700  optional string full_jid = 3;
1701  // Timeout in seconds for client to remain active.
1702  optional uint64 timeout_secs = 4;
1703
1704  // optional bool update_last_seen_timestamp = 5;
1705}
1706
1707message SetActiveClientResponse {
1708  optional ResponseHeader response_header = 1;
1709  //optional ClientSetActiveClientError serror = 2;
1710  optional uint64 client_last_seen_timestamp_usec = 3;
1711  optional uint64 last_seen_delta_usec = 4;
1712}
1713
1714message SetConversationLevelRequest {
1715  optional RequestHeader request_header = 1;
1716  optional ConversationId conversation_id = 2;
1717  optional NotificationLevel level = 3;
1718  optional uint32 revert_timeout_secs = 4;
1719}
1720
1721message SetConversationLevelResponse {
1722  optional ResponseHeader response_header = 1;
1723  optional uint64 timestamp = 2;
1724}
1725
1726message SetConversationNotificationLevelRequest {
1727  optional RequestHeader request_header = 1;
1728  optional ConversationId conversation_id = 2;
1729  optional NotificationLevel level = 3;
1730}
1731
1732message SetConversationNotificationLevelResponse {
1733  optional ResponseHeader response_header = 1;
1734  optional uint64 timestamp = 2;
1735}
1736
1737message SetFocusRequest {
1738  optional RequestHeader request_header = 1;
1739  optional ConversationId conversation_id = 2;
1740  optional FocusType type = 3;
1741  optional uint32 timeout_secs = 4;
1742}
1743
1744message SetFocusResponse {
1745  optional ResponseHeader response_header = 1;
1746  optional uint64 timestamp = 2;
1747}
1748
1749message SetGroupLinkSharingEnabledRequest {
1750  optional RequestHeader request_header = 1;
1751  optional EventRequestHeader event_request_header = 2;
1752  // New group link sharing status.
1753  optional GroupLinkSharingStatus group_link_sharing_status = 4;
1754
1755}
1756
1757message SetGroupLinkSharingEnabledResponse {
1758  optional ResponseHeader response_header = 1;
1759  // Created event of type EVENT_TYPE_GROUP_LINK_SHARING_MODIFICATION.
1760  optional Event created_event = 2;
1761  // Updated conversation.
1762  optional Conversation updated_conversation = 3;
1763}
1764
1765
1766// Allows setting one or more of the included presence-related settings.
1767message SetPresenceRequest {
1768  optional RequestHeader request_header = 1;
1769  optional PresenceStateSetting presence_state_setting = 2;
1770  optional DndSetting dnd_setting = 3;
1771  optional DesktopOffSetting desktop_off_setting = 5;
1772  //optional InCallSetting in_call_setting = 7;
1773  optional MoodSetting mood_setting = 8;
1774}
1775
1776message SetPresenceResponse {
1777  optional ResponseHeader response_header = 1;
1778}
1779
1780message SetTypingRequest {
1781  optional RequestHeader request_header = 1;
1782  optional ConversationId conversation_id = 2;
1783  optional TypingType type = 3;
1784}
1785
1786message SetTypingResponse {
1787  optional ResponseHeader response_header = 1;
1788  optional uint64 timestamp = 2;
1789}
1790
1791message UnreadConversationState {
1792  optional ConversationId conversation_id = 1;
1793  optional uint64 timestamp = 2;
1794}
1795
1796message SyncAllNewEventsRequest {
1797  optional RequestHeader request_header = 1;
1798  // Timestamp after which to return all new events.
1799  optional uint64 last_sync_timestamp = 2;
1800  //repeated LocalState local_state = 3;
1801  optional uint64 max_total_events = 4;
1802  repeated SyncFilter sync_filter = 5;
1803  optional bool no_missed_events_expected = 6;
1804  optional UnreadConversationState unread_state = 7;
1805  optional uint64 max_response_size_bytes = 8;
1806}
1807
1808message SyncAllNewEventsResponse {
1809  optional ResponseHeader response_header = 1;
1810  optional uint64 sync_timestamp = 2;
1811  repeated ConversationState conversation_state = 3;
1812  optional bool conversation_ids_only = 4;
1813  optional InvitationState invitation_state = 5;
1814  optional bool clear_cache_and_resync = 6;
1815}
1816
1817message SyncRecentConversationsRequest {
1818  optional RequestHeader request_header = 1;
1819  optional uint64 end_timestamp = 2;
1820  optional uint64 max_conversations = 3;
1821  optional uint64 max_events_per_conversation = 4;
1822  repeated SyncFilter sync_filter = 5;
1823}
1824
1825message SyncRecentConversationsResponse {
1826  optional ResponseHeader response_header = 1;
1827  optional uint64 sync_timestamp = 2;
1828  repeated ConversationState conversation_state = 3;
1829  optional uint64 continuation_end_timestamp = 4;
1830  optional InvitationState invitation_state = 5;
1831}
1832
1833message UpdateWatermarkRequest {
1834  optional RequestHeader request_header = 1;
1835  optional ConversationId conversation_id = 2;
1836  optional uint64 last_read_timestamp = 3;
1837}
1838
1839message UpdateWatermarkResponse {
1840  optional ResponseHeader response_header = 1;
1841}
1842