### Administer Identities using Python Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Provides a Python example for creating, listing, and deleting identities via the admin API. This operation requires an administrator client key and uses `identity_admin_pb2` and related types. ```python from olvid.daemon.services.v1 import admin_service_pb2_grpc from olvid.daemon.admin.v1 import identity_admin_pb2 from olvid.daemon.datatypes.v1 import identity_pb2 # Must use admin key admin_metadata = [('client-key', 'admin-key-string')] identity_admin_stub = admin_service_pb2_grpc.IdentityAdminServiceStub(channel) # Create a new identity create_identity = identity_admin_pb2.IdentityNewRequest( identity=identity_admin_pb2.IdentityNewSettings( api_key=identity_pb2.ApiKey( permissions=identity_pb2.ApiKeyPermissions( call=True, multi_device=True ) ), server="https://server.olvid.io" ), identity_details=identity_pb2.IdentityDetails( first_name="Bot", last_name="Instance", company="ACME Corp", position="Automation" ) ) new_identity = identity_admin_stub.IdentityNew(create_identity, metadata=admin_metadata) print(f"Created identity: {new_identity.identity.id}") print(f"Display name: {new_identity.identity.display_name}") ``` -------------------------------- ### Manage Persistent Storage using Python Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Shows how to use key-value storage for persisting bot state, both globally and per-discussion. It covers setting, getting, listing, and unsetting data, utilizing `storage_commands_pb2`. ```python from olvid.daemon.services.v1 import command_service_pb2_grpc from olvid.daemon.command.v1 import storage_commands_pb2 storage_stub = command_service_pb2_grpc.StorageCommandServiceStub(channel) discussion_storage_stub = command_service_pb2_grpc.DiscussionStorageCommandServiceStub(channel) # Global storage (identity-scoped) set_request = storage_commands_pb2.StorageSetRequest( key="bot_version", value="v2.1.0" ) storage_stub.StorageSet(set_request, metadata=metadata) set_json = storage_commands_pb2.StorageSetRequest( key="user_preferences", value='{"language": "en", "notifications": true}' ) storage_stub.StorageSet(set_json, metadata=metadata) # Get global storage get_request = storage_commands_pb2.StorageGetRequest(key="bot_version") response = storage_stub.StorageGet(get_request, metadata=metadata) print(f"Stored version: {response.value}") # List all global storage keys list_request = storage_commands_pb2.StorageListRequest() for element in storage_stub.StorageList(list_request, metadata=metadata): print(f"Key: {element.key}, Value: {element.value}") # Discussion-specific storage (per-conversation state) discussion_set = storage_commands_pb2.DiscussionStorageSetRequest( discussion_id=42, key="last_command", value="/help" ) discussion_storage_stub.DiscussionStorageSet(discussion_set, metadata=metadata) discussion_get = storage_commands_pb2.DiscussionStorageGetRequest( discussion_id=42, key="last_command" ) discussion_value = discussion_storage_stub.DiscussionStorageGet(discussion_get, metadata=metadata) print(f"Last command in discussion 42: {discussion_value.value}") # Unset (delete) storage unset_request = storage_commands_pb2.StorageUnsetRequest(key="temporary_data") storage_stub.StorageUnset(unset_request, metadata=metadata) ``` -------------------------------- ### Send, Share, and Track Location (Python) Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Demonstrates sending a single location message, starting live location sharing with periodic updates, and listening to location updates from other users. It utilizes `message_stub` for sending/sharing and `notification_service_pb2_grpc` for listening. Requires `metadata` and a `channel` for gRPC communication. Handles sending, starting, updating, and stopping location sharing, as well as receiving updates. ```python from olvid.daemon.command.v1 import message_commands_pb2 from olvid.daemon.datatypes.v1 import message_pb2 import time # Send a single location message location_request = message_commands_pb2.MessageSendLocationRequest( discussion_id=42, latitude=48.8566, longitude=2.3522, altitude=35.0, precision=10.0, # meters address="Eiffel Tower, Paris" # Optional ) response = message_stub.MessageSendLocation(location_request, metadata=metadata) print(f"Location sent: {response.message.message_location}") # Start sharing live location start_sharing = message_commands_pb2.MessageStartLocationSharingRequest( discussion_id=42, latitude=48.8566, longitude=2.3522, altitude=35.0, precision=10.0 ) share_response = message_stub.MessageStartLocationSharing(start_sharing, metadata=metadata) location_message_id = share_response.message.id # Periodically update location (e.g., every 30 seconds) for i in range(10): time.sleep(30) update_request = message_commands_pb2.MessageUpdateLocationSharingRequest( message_id=location_message_id, latitude=48.8566 + (i * 0.001), # Simulated movement longitude=2.3522 + (i * 0.001), altitude=35.0, precision=10.0 ) message_stub.MessageUpdateLocationSharing(update_request, metadata=metadata) # Stop sharing location end_request = message_commands_pb2.MessageEndLocationSharingRequest( message_id=location_message_id ) message_stub.MessageEndLocationSharing(end_request, metadata=metadata) # Listen to location updates from others location_notification_stub = notification_service_pb2_grpc.MessageNotificationServiceStub(channel) location_update_request = message_notifications_pb2.MessageLocationSharingUpdateSubscribeRequest( filter=message_notifications_pb2.MessageLocationSharingUpdateFilter( discussion_id=42 ) ) for notification in location_notification_stub.MessageLocationSharingUpdateSubscribe( location_update_request, metadata=metadata ): loc = notification.message.message_location print(f"Location update from {notification.message.sender_id}: " f"({loc.latitude}, {loc.longitude}) at {loc.timestamp}") ``` -------------------------------- ### Python: Complete Olvid Echo Bot with File Support Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt A full-featured Olvid bot written in Python that echoes messages, handles attachments, and responds to various commands. It uses gRPC for communication with the Olvid daemon, subscribing to message notifications and sending responses. Requires installation of Olvid protobuf generated code and gRPC libraries. ```python import grpc import threading from olvid.daemon.services.v1 import command_service_pb2_grpc, notification_service_pb2_grpc from olvid.daemon.command.v1 import message_commands_pb2, discussion_commands_pb2 from olvid.daemon.notification.v1 import message_notifications_pb2 class OlvidEchoBot: def __init__(self, host, port, client_key): self.channel = grpc.insecure_channel(f'{host}:{port}') self.metadata = [('client-key', client_key)] self.message_stub = command_service_pb2_grpc.MessageCommandServiceStub(self.channel) self.discussion_stub = command_service_pb2_grpc.DiscussionCommandServiceStub(self.channel) self.notification_stub = notification_service_pb2_grpc.MessageNotificationServiceStub(self.channel) def send_message(self, discussion_id, body, reply_id=None): request = message_commands_pb2.MessageSendRequest( discussion_id=discussion_id, body=body, reply_id=reply_id ) return self.message_stub.MessageSend(request, metadata=self.metadata) def handle_command(self, message): if message.body.startswith('/'): cmd = message.body.split()[0] if cmd == '/help': help_text = """Available commands: /help - Show this message /info - Show discussion info /ping - Respond with pong /echo - Echo your text""" self.send_message(message.discussion_id, help_text, reply_id=message.id) return True elif cmd == '/ping': self.send_message(message.discussion_id, "pong!", reply_id=message.id) return True elif cmd == '/info': disc = self.discussion_stub.DiscussionGet( discussion_commands_pb2.DiscussionGetRequest(discussion_id=message.discussion_id), metadata=self.metadata ).discussion info = f"Discussion: {disc.title}\nID: {disc.id}" self.send_message(message.discussion_id, info, reply_id=message.id) return True elif cmd == '/echo': text = message.body[6:].strip() # Remove '/echo ' self.send_message(message.discussion_id, text, reply_id=message.id) return True return False def listen(self): print("Bot started, listening for messages...") request = message_notifications_pb2.MessageReceivedSubscribeRequest() try: for notification in self.notification_stub.MessageReceivedSubscribe( request, metadata=self.metadata ): msg = notification.message # Ignore own messages (sender_id == 0 means you sent it) if msg.sender_id == 0: continue print(f"Received: {msg.body} from {msg.sender_id}") # Handle commands if self.handle_command(msg): continue # Default: Echo the message back if msg.attachments_count > 0: response = f"Received your message with {msg.attachments_count} attachment(s)" else: response = f"Echo: {msg.body}" self.send_message(msg.discussion_id, response, reply_id=msg.id) except grpc.RpcError as e: print(f"Error: {e.code()}, {e.details()}") except KeyboardInterrupt: print("\nBot stopped") # Run the bot if __name__ == "__main__": bot = OlvidEchoBot( host='localhost', port=50051, client_key='your-client-key-here' ) bot.listen() ``` -------------------------------- ### Listen to Group Events with Python Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Python code to subscribe to group-related notifications from the Olvid daemon. This example demonstrates listening for member join events and extracting associated permissions. ```python from olvid.daemon.services.v1 import notification_service_pb2_grpc from olvid.daemon.notification.v1 import group_notifications_pb2 # Assuming 'channel' and 'metadata' are pre-defined group_notification_stub = notification_service_pb2_grpc.GroupNotificationServiceStub(channel) # Subscribe to member join events join_request = group_notifications_pb2.GroupMemberJoinedSubscribeRequest( filter=group_notifications_pb2.GroupMemberJoinedFilter( group_id=group_id # Optional: filter by specific group ) ) for notification in group_notification_stub.GroupMemberJoinedSubscribe(join_request, metadata=metadata): print(f"Member {notification.contact_id} joined group {notification.group_id}") print(f"Permissions: admin={notification.permissions.admin}, " f"send_message={notification.permissions.send_message}") ``` -------------------------------- ### Receive Messages via gRPC Notifications Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Illustrates how to subscribe to real-time message notifications from the Olvid Daemon. This involves setting up a gRPC stream and optionally filtering by discussion ID. The example also shows how to auto-reply to specific messages. ```python from olvid.daemon.services.v1 import notification_service_pb2_grpc from olvid.daemon.notification.v1 import message_notifications_pb2 channel = grpc.insecure_channel('localhost:50051') notification_stub = notification_service_pb2_grpc.MessageNotificationServiceStub(channel) metadata = [('client-key', 'your-client-key')] # Subscribe to incoming messages in a specific discussion request = message_notifications_pb2.MessageReceivedSubscribeRequest( filter=message_notifications_pb2.MessageReceivedFilter( discussion_id=42 # Optional: filter by discussion ) ) try: for notification in notification_stub.MessageReceivedSubscribe(request, metadata=metadata): msg = notification.message print(f"New message from {msg.sender_id}: {msg.body}") print(f"Discussion: {msg.discussion_id}, Attachments: {msg.attachments_count}") # Auto-reply to messages containing "ping" if "ping" in msg.body.lower(): reply_request = message_commands_pb2.MessageSendRequest( discussion_id=msg.discussion_id, body="pong!", reply_id=msg.id ) message_stub.MessageSend(reply_request, metadata=metadata) except grpc.RpcError as e: print(f"Error: {e.code()}, {e.details()}") ``` -------------------------------- ### Authenticate and Create Client Keys with gRPC Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Demonstrates how to authenticate with the Olvid Daemon using client keys and create new identity-scoped keys. It requires the `grpcio` library and specific protobuf modules. This is crucial for authorizing subsequent API calls. ```python import grpc from olvid.daemon.services.v1 import admin_service_pb2_grpc, admin_service_pb2 from olvid.daemon.admin.v1 import client_key_admin_pb2 # Connect as admin to create a new client key channel = grpc.insecure_channel('localhost:50051') admin_stub = admin_service_pb2_grpc.ClientKeyAdminServiceStub(channel) # Add admin key to metadata admin_metadata = [('client-key', 'admin-secret-key-string')] # Create a new identity-scoped key for a bot request = client_key_admin_pb2.ClientKeyNewRequest( client_key=client_key_admin_pb2.ClientKey( name="telegram-bot", identity_id=5 # Scope to identity 5; use 0 for admin key ) ) response = admin_stub.ClientKeyNew(request, metadata=admin_metadata) bot_key = response.client_key.key # Save this - it only appears once! # Use the bot key for subsequent operations bot_metadata = [('client-key', bot_key)] ``` -------------------------------- ### Managing Contacts using Python Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Demonstrates initiating contact management operations including listing contacts with filtering, retrieving individual contact details, and initiating new contact additions via invitations. Requires protobuf generated files for contact and invitation services. ```python from olvid.daemon.services.v1 import command_service_pb2_grpc from olvid.daemon.command.v1 import contact_commands_pb2, invitation_commands_pb2 # contact_stub = command_service_pb2_grpc.ContactCommandServiceStub(channel) # invitation_stub = command_service_pb2_grpc.InvitationCommandServiceStub(channel) # Example usage (add specific calls as needed): # List contacts: # contact_list_request = contact_commands_pb2.ContactListRequest() # for contact in contact_stub.ContactList(contact_list_request, metadata=metadata): # print(f"Contact: {contact.display_name}") # Invite a contact: # invite_request = invitation_commands_pb2.InvitationCreateRequest( # user_id=invitation_commands_pb2.UserId(id=123), # message="Let's connect on Olvid!" # ) # invitation_stub.InvitationCreate(invite_request, metadata=metadata) ``` -------------------------------- ### Authentication and Client Key Management Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt This section covers how to authenticate with the Olvid Daemon using client keys, including creating new identity-scoped keys for bots and using admin keys for daemon-wide access. ```APIDOC ## Authentication with Client Keys ### Description Authenticates with the daemon using client keys. Admin keys (identity_id=0) grant full daemon access, while identity-scoped keys restrict access to a single identity's data. This example demonstrates creating a new identity-scoped key for a bot. ### Method (gRPC) ### Endpoint (gRPC Service: ClientKeyAdminService, Method: ClientKeyNew) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **client_key** (ClientKey) - Required - The details of the client key to create. - **name** (string) - Required - The name of the client key. - **identity_id** (int) - Required - The ID of the identity to scope the key to. Use 0 for admin keys. ### Request Example ```python import grpc from olvid.daemon.services.v1 import admin_service_pb2_grpc, admin_service_pb2 from olvid.daemon.admin.v1 import client_key_admin_pb2 channel = grpc.insecure_channel('localhost:50051') admin_stub = admin_service_pb2_grpc.ClientKeyAdminServiceStub(channel) admin_metadata = [('client-key', 'admin-secret-key-string')] request = client_key_admin_pb2.ClientKeyNewRequest( client_key=client_key_admin_pb2.ClientKey( name="telegram-bot", identity_id=5 ) ) response = admin_stub.ClientKeyNew(request, metadata=admin_metadata) bot_key = response.client_key.key ``` ### Response #### Success Response (200) - **client_key** (ClientKey) - The newly created client key. - **key** (string) - The secret key string. This is only returned once upon creation. - **name** (string) - The name of the client key. - **identity_id** (int) - The identity ID the key is scoped to. #### Response Example ```json { "client_key": { "key": "your-new-bot-key-string", "name": "telegram-bot", "identity_id": 5 } } ``` ``` -------------------------------- ### Create and Manage Groups with Python Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Python code for creating and managing groups using the Olvid daemon's gRPC services. This includes creating standard and advanced groups with customizable configurations and updating group memberships. ```python from olvid.daemon.services.v1 import command_service_pb2_grpc from olvid.daemon.command.v1 import group_commands_pb2 from olvid.daemon.datatypes.v1 import group_pb2 # Assuming 'channel' and 'metadata' are pre-defined group_stub = command_service_pb2_grpc.GroupCommandServiceStub(channel) # Create a standard group (all members equal) create_request = group_commands_pb2.GroupNewStandardGroupRequest( name="Project Team", description="Weekly sync and updates", admin_contact_ids=[10, 20, 30] # Initial members (all become admins) ) response = group_stub.GroupNewStandardGroup(create_request, metadata=metadata) group_id = response.group.id print(f"Created group: {group_id}") # Create an advanced group with custom permissions advanced_request = group_commands_pb2.GroupNewAdvancedGroupRequest( name="Company Announcements", description="Read-only for most, admins can post", configuration=group_pb2.AdvancedConfiguration( read_only=True, # Only admins can post by default remote_delete_policy=group_pb2.ADVANCED_CONFIGURATION_REMOTE_DELETE_POLICY_ADMINS ), members=[ group_pb2.GroupMember( contact_id=10, permissions=group_pb2.GroupMemberPermissions( admin=True, send_message=True, remote_delete_anything=True, edit_or_remote_delete_own_messages=True, change_settings=True ) ), group_pb2.GroupMember( contact_id=20, permissions=group_pb2.GroupMemberPermissions( send_message=True, # Can post but not admin edit_or_remote_delete_own_messages=True ) ) ] ) advanced_group = group_stub.GroupNewAdvancedGroup(advanced_request, metadata=metadata) # Update group to add member get_request = group_commands_pb2.GroupGetRequest(group_id=group_id) current_group = group_stub.GroupGet(get_request, metadata=metadata).group updated_group = group_pb2.Group() uupdated_group.CopyFrom(current_group) updated_group.members.append( group_pb2.GroupMember( contact_id=40, permissions=group_pb2.GroupMemberPermissions( send_message=True, edit_or_remote_delete_own_messages=True ) ) ) update_request = group_commands_pb2.GroupUpdateRequest(group=updated_group) group_stub.GroupUpdate(update_request, metadata=metadata) ``` -------------------------------- ### Invitation Management Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Endpoints for generating invitation links and accepting/verifying invitations. ```APIDOC ## POST /api/identity/invitation/link ### Description Generates an invitation link to share with new contacts. ### Method POST ### Endpoint /api/identity/invitation/link ### Parameters #### Query Parameters - **metadata** (object) - Required - Metadata for the request, including authentication tokens. ### Request Example ```json {} ``` ### Response #### Success Response (200) - **invitation_link** (string) - The generated invitation link. #### Response Example ```json { "invitation_link": "https://olvid.com/invite/abcdef12345" } ``` ## POST /api/invitation/accept ### Description Accepts an invitation after receiving an invitation URL. ### Method POST ### Endpoint /api/invitation/accept ### Parameters #### Query Parameters - **metadata** (object) - Required - Metadata for the request, including authentication tokens. #### Request Body - **invitation_id** (integer) - Required - The ID of the invitation to accept. ### Request Example ```json { "invitation_id": 789 } ``` ### Response #### Success Response (200) (No specific fields mentioned, likely indicates success) ## POST /api/invitation/sas ### Description Exchanges a Short Authentication String (SAS) for verification purposes after an invitation is accepted. ### Method POST ### Endpoint /api/invitation/sas ### Parameters #### Query Parameters - **metadata** (object) - Required - Metadata for the request, including authentication tokens. #### Request Body - **invitation_id** (integer) - Required - The ID of the invitation associated with the SAS. - **sas** (string) - Required - The user-entered verification code (SAS). ### Request Example ```json { "invitation_id": 789, "sas": "1234" } ``` ### Response #### Success Response (200) (No specific fields mentioned, likely indicates success) ``` -------------------------------- ### Group Management Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt APIs for creating, updating, and managing groups with different permission models. ```APIDOC ## POST /api/groups/new/standard ### Description Creates a new standard group where all members have equal permissions. ### Method POST ### Endpoint /api/groups/new/standard ### Parameters #### Query Parameters - **metadata** (object) - Required - Metadata for the request, including authentication tokens. #### Request Body - **name** (string) - Required - The name of the group. - **description** (string) - Optional - A description for the group. - **admin_contact_ids** (array) - Required - A list of contact IDs to be added as initial members and administrators. - **(integer)** - Contact ID. ### Request Example ```json { "name": "Project Team", "description": "Weekly sync and updates", "admin_contact_ids": [10, 20, 30] } ``` ### Response #### Success Response (200) - **group** (object) - The newly created group object. - **id** (integer) - The unique identifier of the group. #### Response Example ```json { "group": { "id": 101 } } ``` ## POST /api/groups/new/advanced ### Description Creates a new advanced group with custom permission configurations. ### Method POST ### Endpoint /api/groups/new/advanced ### Parameters #### Query Parameters - **metadata** (object) - Required - Metadata for the request, including authentication tokens. #### Request Body - **name** (string) - Required - The name of the group. - **description** (string) - Optional - A description for the group. - **configuration** (object) - Optional - Advanced configuration settings for the group. - **read_only** (boolean) - If true, only admins can post by default. - **remote_delete_policy** (enum) - Policy for remote deletion. Possible values: `ADVANCED_CONFIGURATION_REMOTE_DELETE_POLICY_ADMINS`. - **members** (array) - Optional - A list of initial members and their permissions. - **contact_id** (integer) - Required - The ID of the contact. - **permissions** (object) - The permissions for the group member. - **admin** (boolean) - Whether the member is an administrator. - **send_message** (boolean) - Whether the member can send messages. - **remote_delete_anything** (boolean) - Whether the member can remotely delete any message. - **edit_or_remote_delete_own_messages** (boolean) - Whether the member can edit or remotely delete their own messages. - **change_settings** (boolean) - Whether the member can change group settings. ### Request Example ```json { "name": "Company Announcements", "description": "Read-only for most, admins can post", "configuration": { "read_only": true, "remote_delete_policy": "ADVANCED_CONFIGURATION_REMOTE_DELETE_POLICY_ADMINS" }, "members": [ { "contact_id": 10, "permissions": { "admin": true, "send_message": true, "remote_delete_anything": true, "edit_or_remote_delete_own_messages": true, "change_settings": true } }, { "contact_id": 20, "permissions": { "send_message": true, "edit_or_remote_delete_own_messages": true } } ] } ``` ### Response #### Success Response (200) - **group** (object) - The newly created advanced group object. - **id** (integer) - The unique identifier of the group. #### Response Example ```json { "group": { "id": 102 } } ``` ## POST /api/groups/get ### Description Retrieves details of a specific group. ### Method POST ### Endpoint /api/groups/get ### Parameters #### Query Parameters - **metadata** (object) - Required - Metadata for the request, including authentication tokens. #### Request Body - **group_id** (integer) - Required - The ID of the group to retrieve. ### Request Example ```json { "group_id": 101 } ``` ### Response #### Success Response (200) - **group** (object) - The group object with its current details. - **id** (integer) - The unique identifier of the group. - **name** (string) - The name of the group. - **description** (string) - The description of the group. - **members** (array) - A list of members in the group. - **contact_id** (integer) - The ID of the contact. - **permissions** (object) - The permissions of the member. #### Response Example ```json { "group": { "id": 101, "name": "Project Team", "description": "Weekly sync and updates", "members": [ { "contact_id": 10, "permissions": { "admin": true, "send_message": true, "remote_delete_anything": true, "edit_or_remote_delete_own_messages": true, "change_settings": true } } ] } } ``` ## POST /api/groups/update ### Description Updates an existing group's details or membership. ### Method POST ### Endpoint /api/groups/update ### Parameters #### Query Parameters - **metadata** (object) - Required - Metadata for the request, including authentication tokens. #### Request Body - **group** (object) - Required - The group object with updated information. - **id** (integer) - Required - The ID of the group to update. - **name** (string) - Optional - The new name for the group. - **description** (string) - Optional - The new description for the group. - **members** (array) - Optional - The updated list of members. Appending a member will add them. - **contact_id** (integer) - Required - The ID of the contact. - **permissions** (object) - The permissions for the group member. ### Request Example ```json { "group": { "id": 101, "members": [ { "contact_id": 10, "permissions": { "admin": true, "send_message": true, "remote_delete_anything": true, "edit_or_remote_delete_own_messages": true, "change_settings": true } }, { "contact_id": 40, "permissions": { "send_message": true, "edit_or_remote_delete_own_messages": true } } ] } } ``` ### Response #### Success Response (200) (No specific fields mentioned, likely indicates success) ``` -------------------------------- ### List Contacts and Manage Invitations with Python Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Python code to list contacts with one-to-one discussions, retrieve invitation links, accept invitations, and exchange SAS for verification. It utilizes various protobuf modules for command and invitation services. ```python from olvid.daemon.services.v1 import contact_commands_pb2_grpc from olvid.daemon.services.v1 import command_service_pb2_grpc from olvid.daemon.command.v1 import message_commands_pb2 from olvid.daemon.command.v1 import invitation_commands_pb2 # Assuming 'channel' and 'metadata' are pre-defined contact_stub = contact_commands_pb2_grpc.ContactCommandServiceStub(channel) identity_stub = command_service_pb2_grpc.IdentityCommandServiceStub(channel) invitation_stub = command_service_pb2_grpc.InvitationCommandServiceStub(channel) # List all contacts with one-to-one discussions list_request = contact_commands_pb2.ContactListRequest( filter=contact_commands_pb2.ContactFilter( display_name_search="John", # Optional: search by name one_to_one=contact_commands_pb2.CONTACT_FILTER_ONE_TO_ONE_IS ) ) contacts = [] for contact in contact_stub.ContactList(list_request, metadata=metadata): contacts.append(contact) print(f"Contact: {contact.display_name} (ID: {contact.id})") print(f" Company: {contact.details.company}, Position: {contact.details.position}") print(f" Devices: {contact.device_count}, Channels: {contact.established_channel_count}") # Get invitation link to share with new contact invitation_link = identity_stub.IdentityGetInvitationLink( message_commands_pb2.IdentityGetInvitationLinkRequest(), metadata=metadata ) print(f"Share this link: {invitation_link.invitation_link}") # Accept an invitation (after receiving invitation URL) accept_request = invitation_commands_pb2.InvitationAcceptRequest( invitation_id=789 ) invitation_stub.InvitationAccept(accept_request, metadata=metadata) # Exchange SAS (Short Authentication String) for verification sas_request = invitation_commands_pb2.InvitationSasRequest( invitation_id=789, sas="1234" # User-entered verification code ) invitation_stub.InvitationSas(sas_request, metadata=metadata) ``` -------------------------------- ### Admin Operations: Identity Management Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Create, list, and delete identities using admin privileges. Requires an admin client key. ```APIDOC ## Identity Management API (Admin) ### Description Allows administrators to manage identities within the system. This includes creating new identities and retrieving their details. Requires administrative credentials. ### Method `POST` ### Endpoint `/admin/identity/new ### Parameters #### Request Body - **identity** (object) - Required - Settings for the new identity. - **api_key** (object) - Required - API key configuration. - **permissions** (object) - Required - Permissions for the API key. - **call** (boolean) - Required - Whether the API key can make calls. - **multi_device** (boolean) - Required - Whether the API key supports multi-device. - **server** (string) - Required - The server URL for the identity. - **identity_details** (object) - Optional - Details about the identity. - **first_name** (string) - Optional - The first name of the identity. - **last_name** (string) - Optional - The last name of the identity. - **company** (string) - Optional - The company associated with the identity. - **position** (string) - Optional - The position within the company. ### Request Example ```json { "identity": { "api_key": { "permissions": { "call": true, "multi_device": true } }, "server": "https://server.olvid.io" }, "identity_details": { "first_name": "Bot", "last_name": "Instance", "company": "ACME Corp", "position": "Automation" } } ``` ### Response #### Success Response (200) - **identity** (object) - The newly created identity object. - **id** (string) - The unique ID of the identity. - **display_name** (string) - The display name of the identity. (Other identity fields may be present) #### Response Example ```json { "identity": { "id": "identity-uuid-12345", "display_name": "Bot Instance" } } ``` ``` -------------------------------- ### Downloading File Attachments using Python Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Downloads attachment files from messages using server streaming for efficient handling of large files. It first retrieves message and attachment metadata, then downloads the attachment content in chunks. Requires protobuf generated files for command and attachment services. ```python from olvid.daemon.services.v1 import command_service_pb2_grpc from olvid.daemon.command.v1 import attachment_commands_pb2, message_commands_pb2 from olvid.daemon.datatypes.v1 import attachment_pb2 # attachment_stub = command_service_pb2_grpc.AttachmentCommandServiceStub(channel) # message_stub = command_service_pb2_grpc.MessageCommandServiceStub(channel) # First, get attachment metadata from message # message_list_request = message_commands_pb2.MessageListRequest( # filter=message_commands_pb2.MessageFilter( # discussion_id=42, # attachment=message_commands_pb2.MESSAGE_FILTER_ATTACHMENT_HAVE # ) # ) # for message in message_stub.MessageList(message_list_request, metadata=metadata): # if message.attachments_count > 0: # # List attachments for this message # attachment_list_request = attachment_commands_pb2.AttachmentListRequest( # filter=attachment_commands_pb2.AttachmentFilter( # message_id=message.id # ) # ) # for attachment in attachment_stub.AttachmentList(attachment_list_request, metadata=metadata): # print(f"Downloading {attachment.file_name} ({attachment.size} bytes)") # # Download attachment content # download_request = attachment_commands_pb2.AttachmentDownloadRequest( # attachment_id=attachment.id # ) # output_path = f"/downloads/{attachment.file_name}" # with open(output_path, 'wb') as f: # for chunk in attachment_stub.AttachmentDownload(download_request, metadata=metadata): # f.write(chunk.payload) # print(f"Saved to {output_path}") ``` -------------------------------- ### Contact Management APIs Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt APIs for managing contacts, including listing contacts with filtering, retrieving detailed contact information, and initiating contact invitations. ```APIDOC ## Contact Management Endpoints ### Description Provides endpoints for managing user contacts. This includes listing contacts with various filtering options, retrieving specific contact details, and sending contact invitations. ### Endpoints #### 1. List Contacts - **Method:** GET - **Endpoint:** `/contacts` - **Description:** Retrieves a list of contacts, with optional filtering capabilities. - **Query Parameters:** - `filter` (string) - Optional - Criteria to filter the contacts (e.g., 'online', 'offline', 'has_message'). - `limit` (int) - Optional - Maximum number of contacts to return. - `offset` (int) - Optional - Number of contacts to skip (for pagination). #### 2. Get Contact Details - **Method:** GET - **Endpoint:** `/contacts/{contact_id}` - **Description:** Retrieves detailed information for a specific contact. - **Path Parameters:** - `contact_id` (string) - Required - The unique identifier of the contact. #### 3. Add Contact (Invite) - **Method:** POST - **Endpoint:** `/invitations/contact` - **Description:** Sends an invitation to a new contact. - **Request Body:** - `email` (string) - Required - The email address of the person to invite. - `message` (string) - Optional - A personal message to include with the invitation. ### Example Usage (Conceptual) ```python # Assuming 'contact_stub' and 'invitation_stub' are initialized gRPC stubs # List contacts with a filter # contacts = contact_stub.ContactList(contact_commands_pb2.ContactListRequest(filter='online')) # Get details for a specific contact # contact_details = contact_stub.ContactGet(contact_commands_pb2.ContactGetRequest(contact_id='user-123')) # Send a contact invitation # invitation_stub.SendContactInvitation(invitation_commands_pb2.InvitationSendRequest(email='new.contact@example.com', message='Hello!')) ``` ``` -------------------------------- ### Persistent Storage API Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt Use key-value storage to persist bot state, either globally or per-discussion, with automatic backup resilience. ```APIDOC ## Global Storage API ### Description Provides key-value storage accessible globally across all discussions and identities. Ideal for storing bot-wide configurations or state. ### Method `POST` (for set/unset), `GET` (for get), `LIST` (for list) ### Endpoint `/storage ### Parameters #### StorageSetRequest (POST) - **key** (string) - Required - The key for the storage item. - **value** (string) - Required - The value to store. Can be JSON stringified. #### StorageGetRequest (GET) - **key** (string) - Required - The key of the item to retrieve. #### StorageListRequest (LIST) (No parameters required) #### StorageUnsetRequest (POST) - **key** (string) - Required - The key of the item to delete. ### Request Example (SET) ```json { "key": "bot_version", "value": "v2.1.0" } ``` ### Request Example (SET JSON) ```json { "key": "user_preferences", "value": "{\"language\": \"en\", \"notifications\": true}" } ``` ### Request Example (GET) ```json { "key": "bot_version" } ``` ### Response #### Success Response (GET) - **value** (string) - The retrieved value associated with the key. #### Success Response (LIST) - An array of objects, each with: - **key** (string) - The storage key. - **value** (string) - The stored value. #### Response Example (GET) ```json { "value": "v2.1.0" } ``` ## Discussion Storage API ### Description Provides key-value storage specific to a particular discussion. Useful for maintaining conversation context or state within a single discussion. ### Method `POST` (for set/unset), `GET` (for get) ### Endpoint `/storage/discussion ### Parameters #### DiscussionStorageSetRequest (POST) - **discussion_id** (integer) - Required - The ID of the discussion. - **key** (string) - Required - The key for the storage item. - **value** (string) - Required - The value to store. #### DiscussionStorageGetRequest (GET) - **discussion_id** (integer) - Required - The ID of the discussion. - **key** (string) - Required - The key of the item to retrieve. ### Request Example (SET) ```json { "discussion_id": 42, "key": "last_command", "value": "/help" } ``` ### Request Example (GET) ```json { "discussion_id": 42, "key": "last_command" } ``` ### Response #### Success Response (GET) - **value** (string) - The retrieved value associated with the key in the specified discussion. #### Response Example (GET) ```json { "value": "/help" } ``` ``` -------------------------------- ### Location Sharing and Tracking API Source: https://context7.com/olvid-io/olvid-bot-protobuf/llms.txt This API allows users to send static location messages, share their live location with periodic updates, and subscribe to location updates from other users. ```APIDOC ## Sharing and Tracking Location ### Description Enables sending static location messages, sharing live location with periodic updates, and subscribing to location updates from others. ### Method - `MessageSendLocation`: Sends a single location message. - `MessageStartLocationSharing`: Initiates live location sharing. - `MessageUpdateLocationSharing`: Updates the sender's location during an active sharing session. - `MessageEndLocationSharing`: Stops an active live location sharing session. - `MessageLocationSharingUpdateSubscribe`: Subscribes to receive real-time location updates from other users. ### Endpoint N/A (These are gRPC methods called via client stubs) ### Parameters See individual method descriptions below. ### Request Body Examples #### `MessageSendLocationRequest` ```protobuf message MessageSendLocationRequest { int64 discussion_id = 1; double latitude = 2; double longitude = 3; optional double altitude = 4; optional double precision = 5; optional string address = 6; } ``` #### `MessageStartLocationSharingRequest` ```protobuf message MessageStartLocationSharingRequest { int64 discussion_id = 1; double latitude = 2; double longitude = 3; optional double altitude = 4; optional double precision = 5; } ``` #### `MessageUpdateLocationSharingRequest` ```protobuf message MessageUpdateLocationSharingRequest { message_pb2.MessageId message_id = 1; double latitude = 2; double longitude = 3; optional double altitude = 4; optional double precision = 5; } ``` #### `MessageEndLocationSharingRequest` ```protobuf message MessageEndLocationSharingRequest { message_pb2.MessageId message_id = 1; } ``` #### `MessageLocationSharingUpdateSubscribeRequest` ```protobuf message MessageLocationSharingUpdateSubscribeRequest { MessageLocationSharingUpdateFilter filter = 1; } message MessageLocationSharingUpdateFilter { int64 discussion_id = 1; } ``` ### Request Example (Sending a location) ```python # Assuming message_stub is configured location_request = message_commands_pb2.MessageSendLocationRequest( discussion_id=42, latitude=48.8566, longitude=2.3522, altitude=35.0, precision=10.0, # meters address="Eiffel Tower, Paris" # Optional ) response = message_stub.MessageSendLocation(location_request, metadata=metadata) print(f"Location sent: {response.message.message_location}") ``` ### Request Example (Sharing live location) ```python # Assuming message_stub and metadata are configured start_sharing = message_commands_pb2.MessageStartLocationSharingRequest( discussion_id=42, latitude=48.8566, longitude=2.3522, altitude=35.0, precision=10.0 ) share_response = message_stub.MessageStartLocationSharing(start_sharing, metadata=metadata) location_message_id = share_response.message.id # Periodically update location (e.g., every 30 seconds) for i in range(10): time.sleep(30) update_request = message_commands_pb2.MessageUpdateLocationSharingRequest( message_id=location_message_id, latitude=48.8566 + (i * 0.001), # Simulated movement longitude=2.3522 + (i * 0.001), altitude=35.0, precision=10.0 ) message_stub.MessageUpdateLocationSharing(update_request, metadata=metadata) # Stop sharing location end_request = message_commands_pb2.MessageEndLocationSharingRequest( message_id=location_message_id ) message_stub.MessageEndLocationSharing(end_request, metadata=metadata) ``` ### Request Example (Listening to location updates) ```python # Assuming location_notification_stub is configured location_update_request = message_notifications_pb2.MessageLocationSharingUpdateSubscribeRequest( filter=message_notifications_pb2.MessageLocationSharingUpdateFilter( discussion_id=42 ) ) for notification in location_notification_stub.MessageLocationSharingUpdateSubscribe( location_update_request, metadata=metadata ): loc = notification.message.message_location print(f"Location update from {notification.message.sender_id}: " f"({loc.latitude}, {loc.longitude}) at {loc.timestamp}") ``` ### Response #### Success Response (Send/Start/Update/End) - **message** (Message) - The resulting message object, containing details of the sent or shared location. #### Success Response (Subscribe Stream) - **message** (Message) - Contains location data including latitude, longitude, altitude, precision, and timestamp. - **message.sender_id** (string) - The ID of the user sending the location update. #### Response Example (Sent Location) ```json { "message": { "message_location": { "latitude": 48.8566, "longitude": 2.3522, "altitude": 35.0, "precision": 10.0, "address": "Eiffel Tower, Paris" } } } ``` #### Response Example (Location Update Stream) ```json { "message": { "sender_id": "user456", "message_location": { "latitude": 48.8576, "longitude": 2.3532, "altitude": 35.0, "precision": 10.0, "timestamp": "2023-10-27T10:00:00Z" } } } ``` ```