Files
supabase/apps/docs/content/guides/realtime/broadcast.mdx
Guilherme Souza f2ab50ea45 docs(python): add reference docs for python realtime (#28680)
* docs(python): add reference docs for python realtime

* python realtime guides

* remove $ref
2024-08-16 06:56:51 -03:00

640 lines
16 KiB
Plaintext

---
title: 'Broadcast'
subtitle: 'Send and receive messages using Realtime Broadcast'
description: 'Send and receive messages using Realtime Broadcast'
---
Let's explore how to implement Realtime Broadcast to send messages between clients.
## Usage
You can use the Supabase client libraries to send and receive Broadcast messages.
### Initialize the client
Go to your Supabase project's [API Settings](https://supabase.com/dashboard/project/_/settings/api) and grab the `URL` and `anon` public API key.
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
queryGroup="language"
>
<TabPanel id="js" label="JavaScript">
```js
import { createClient } from '@supabase/supabase-js'
const SUPABASE_URL = 'https://<project>.supabase.co'
const SUPABASE_KEY = '<your-anon-key>'
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
```
</TabPanel>
<TabPanel id="dart" label="Dart">
```dart
import 'package:supabase_flutter/supabase_flutter.dart';
void main() async {
Supabase.initialize(
url: 'https://<project>.supabase.co',
anonKey: '<your-anon-key>',
);
runApp(MyApp());
}
final supabase = Supabase.instance.client;
```
</TabPanel>
<TabPanel id="swift" label="Swift">
```swift
import Supabase
let SUPABASE_URL = "https://<project>.supabase.co"
let SUPABASE_KEY = "<your-anon-key>"
let supabase = SupabaseClient(supabaseURL: URL(string: SUPABASE_URL)!, supabaseKey: SUPABASE_KEY)
```
</TabPanel>
<TabPanel id="kotlin" label="Kotlin">
```kotlin
val supabaseUrl = "https://<project>.supabase.co"
val supabaseKey = "<your-anon-key>"
val supabase = createSupabaseClient(supabaseUrl, supabaseKey) {
install(Realtime)
}
```
</TabPanel>
<TabPanel id="python" label="Python">
```python
from supabase import create_client
URL = "https://<project>.supabase.co"
KEY = "<your-anon-key>"
supabase = create_client(URL, KEY)
```
</TabPanel>
</Tabs>
### Listening to broadcast messages
You can provide a callback for the `broadcast` channel to receive message. In this example we will receive any `broadcast` messages in `room-1`:
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
queryGroup="language"
>
<TabPanel id="js" label="JavaScript">
{/* prettier-ignore */}
```js
// Join a room/topic. Can be anything except for 'realtime'.
const channelA = supabase.channel('room-1')
// Simple function to log any messages we receive
function messageReceived(payload) {
console.log(payload)
}
// Subscribe to the Channel
channelA
.on(
'broadcast',
{ event: 'test' },
(payload) => messageReceived(payload)
)
.subscribe()
```
</TabPanel>
<TabPanel id="dart" label="Dart">
```dart
final channelA = supabase.channel('room-1');
// Simple function to log any messages we receive
void messageReceived(payload) {
print(payload);
}
// Subscribe to the Channel
channelA
.onBroadcast(
event: 'test', callback: (payload) => messageReceived(payload))
.subscribe();
```
</TabPanel>
<TabPanel id="swift" label="Swift">
```swift
let channelA = await supabase.channel("room-1")
// Listen for broadcast messages
let broadcastStream = await channelA.broadcast(event: "test")
await channelA.subscribe()
for await event in broadcastStream {
print(event)
}
```
</TabPanel>
<TabPanel id="kotlin" label="Kotlin">
```kotlin
val channelA = supabase.channel("room-1")
//Listen for broadcast messages
val broadcastFlow: Flow<JsonObject> = channelA.broadcastFlow<JsonObject>("test")
.onEach {
println(it)
}
.launchIn(yourCoroutineScope) //you can also use .collect { } here
channelA.subscribe()
```
</TabPanel>
<TabPanel id="python" label="Python">
```python
# Join a room/topic. Can be anything except for 'realtime'.
channel_a = supabase.channel('room-1')
# Simple function to log any messages we receive
def message_received(payload):
print(f"Broadcast received: {payload}")
# Subscribe to the Channel
channel_a
.on_broadcast(
'test',
message_received
)
.subscribe()
```
</TabPanel>
</Tabs>
### Sending broadcast messages
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
queryGroup="language"
>
<TabPanel id="js" label="JavaScript">
We can send Broadcast messages using `channelB.send()`. Let's set up another client to send messages.
{/* prettier-ignore */}
```js
// Join a room/topic. Can be anything except for 'realtime'.
const channelB = supabase.channel('room-1')
channelB.subscribe((status) => {
// Wait for successful connection
if (status !== 'SUBSCRIBED') {
return null
}
// Send a message once the client is subscribed
channelB.send({
type: 'broadcast',
event: 'test',
payload: { message: 'hello, world' },
})
})
```
</TabPanel>
<TabPanel id="dart" label="Dart">
We can send Broadcast messages using `channelB.sendBroadcastMessage()`. Let's set up another client to send messages.
```dart
// Join a room/topic. Can be anything except for 'realtime'.
final channelB = supabase.channel('room-1');
channelB.subscribe((status, error) {
// Wait for successful connection
if (status != RealtimeSubscribeStatus.subscribed) {
return;
}
// Send a message once the client is subscribed
channelB.sendBroadcastMessage(
event: 'test',
payload: {'message': 'hello, world'},
);
});
```
</TabPanel>
<TabPanel id="swift" label="Swift">
We can send Broadcast messages using `channelB.broadcast()`. Let's set up another client to send messages.
```swift
let channelB = await supabase.channel("room-1")
await channelB.subscribe()
try await channelB.broadcast(
event: "test",
message: YourMessage(message: "hello, world!")
)
```
</TabPanel>
<TabPanel id="kotlin" label="Kotlin">
We can send Broadcast messages using `channelB.broadcast()`. Let's set up another client to send messages.
```kotlin
val channelB = supabase.channel("room-1")
channelB.subscribe(blockUntilSubscribed = true) //You can also use the channelA.status flow instead, but this parameter will block the coroutine until the status is joined.
channelB.broadcast(
event = "test",
payload = YourMessage(message = "hello, world!")
)
```
</TabPanel>
<TabPanel id="python" label="Python">
We can send Broadcast messages using `channel_b.send_broadcast()`. Let's set up another client to send messages.
```python
# Join a room/topic. Can be anything except for 'realtime'.
channel_b = supabase.channel('room-1')
def on_subscribe(status, err):
if status != RealtimeSubscribeStates.SUBSCRIBED:
return
# Send a message once the client is subscribed
channel_b.send_broadcast(
'test',
{ "message": 'hello, world' },
)
channel_b.subscribe(on_subscribe)
```
</TabPanel>
</Tabs>
Before sending messages we need to ensure the client is connected, which we have done within the `subscribe()` callback.
## Broadcast options
You can pass configuration options while initializing the Supabase Client.
### Self-send messages
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
queryGroup="language"
>
<TabPanel id="js" label="JavaScript">
By default, broadcast messages are only sent to other clients. You can broadcast messages back to the sender by setting Broadcast's `self` parameter to `true`.
{/* prettier-ignore */}
```js
const myChannel = supabase.channel('room-2', {
config: {
broadcast: { self: true },
},
})
myChannel.on(
'broadcast',
{ event: 'test-my-messages' },
(payload) => console.log(payload)
)
myChannel.subscribe((status) => {
if (status !== 'SUBSCRIBED') { return }
channelC.send({
type: 'broadcast',
event: 'test-my-messages',
payload: { message: 'talking to myself' },
})
})
```
</TabPanel>
<TabPanel id="dart" label="Dart">
By default, broadcast messages are only sent to other clients. You can broadcast messages back to the sender by setting Broadcast's `self` parameter to `true`.
```dart
final myChannel = supabase.channel(
'room-2',
opts: const RealtimeChannelConfig(
self: true,
),
);
myChannel.onBroadcast(
event: 'test-my-messages',
callback: (payload) => print(payload),
);
myChannel.subscribe((status, error) {
if (status != RealtimeSubscribeStatus.subscribed) return;
// channelC.send({
myChannel.sendBroadcastMessage(
event: 'test-my-messages',
payload: {'message': 'talking to myself'},
);
});
```
</TabPanel>
<TabPanel id="swift" label="Swift">
By default, broadcast messages are only sent to other clients. You can broadcast messages back to the sender by setting Broadcast's `receiveOwnBroadcasts` parameter to `true`.
```swift
let myChannel = await supabase.channel("room-2") {
$0.broadcast.receiveOwnBroadcasts = true
}
let broadcastStream = await myChannel.broadcast(event: "test-my-messages")
await myChannel.subscribe()
try await myChannel.broadcast(
event: "test-my-messages",
payload: YourMessage(
message: "talking to myself"
)
)
```
</TabPanel>
<TabPanel id="kotlin" label="Kotlin">
By default, broadcast messages are only sent to other clients. You can broadcast messages back to the sender by setting Broadcast's `receiveOwnBroadcasts` parameter to `true`.
```kotlin
val myChannel = supabase.channel("room-2") {
broadcast {
receiveOwnBroadcasts = true
}
}
val broadcastFlow: Flow<JsonObject> = myChannel.broadcastFlow<JsonObject>("test-my-messages")
.onEach {
println(it)
}
.launchIn(yourCoroutineScope)
myChannel.subscribe(blockUntilSubscribed = true) //You can also use the myChannel.status flow instead, but this parameter will block the coroutine until the status is joined.
myChannel.broadcast(
event = "test-my-messages",
payload = YourMessage(
message = "talking to myself"
)
)
```
</TabPanel>
<TabPanel id="python" label="Python">
By default, broadcast messages are only sent to other clients. You can broadcast messages back to the sender by setting Broadcast's `self` parameter to `True`.
```python
# Join a room/topic. Can be anything except for 'realtime'.
my_channel = supabase.channel('room-2', {"config": {"broadcast": {"self": True}}})
my_channel.on_broadcast(
'test-my-messages',
lambda payload: print(payload)
)
def on_subscribe(status, err):
if status != RealtimeSubscribeStates.SUBSCRIBED:
return
# Send a message once the client is subscribed
channel_b.send_broadcast(
'test-my-messages',
{ "message": 'talking to myself' },
)
my_channel.subscribe(on_subscribe)
```
</TabPanel>
</Tabs>
### Acknowledge messages
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
queryGroup="language"
>
<TabPanel id="js" label="JavaScript">
You can confirm that Realtime received your message by setting Broadcast's `ack` config to `true`.
{/* prettier-ignore */}
```js
const myChannel = supabase.channel('room-3', {
config: {
broadcast: { ack: true },
},
})
myChannel.subscribe(async (status) => {
if (status !== 'SUBSCRIBED') { return }
const serverResponse = await myChannel.send({
type: 'broadcast',
event: 'acknowledge',
payload: {},
})
console.log('serverResponse', serverResponse)
})
```
</TabPanel>
<TabPanel id="dart" label="Dart">
```dart
final myChannel = supabase.channel('room-3',opts: const RealtimeChannelConfig(
ack: true,
),
);
myChannel.subscribe( (status, error) async {
if (status != RealtimeSubscribeStatus.subscribed) return;
final serverResponse = await myChannel.sendBroadcastMessage(
event: 'acknowledge',
payload: {},
);
print('serverResponse: $serverResponse');
});
```
</TabPanel>
<TabPanel id="swift" label="Swift">
You can confirm that Realtime received your message by setting Broadcast's `acknowledgeBroadcasts` config to `true`.
```swift
let myChannel = await supabase.channel("room-3") {
$0.broadcast.acknowledgeBroadcasts = true
}
await myChannel.subscribe()
await myChannel.broadcast(event: "acknowledge", message: [:])
```
</TabPanel>
<TabPanel id="kotlin" label="Kotlin">
By default, broadcast messages are only sent to other clients. You can broadcast messages back to the sender by setting Broadcast's `acknowledgeBroadcasts` parameter to `true`.
```kotlin
val myChannel = supabase.channel("room-2") {
broadcast {
acknowledgeBroadcasts = true
}
}
myChannel.subscribe(blockUntilSubscribed = true) //You can also use the myChannel.status flow instead, but this parameter will block the coroutine until the status is joined.
myChannel.broadcast(event = "acknowledge", buildJsonObject { })
```
</TabPanel>
<TabPanel id="python" label="Python">
Unsupported in Python yet.
</TabPanel>
</Tabs>
Use this to guarantee that the server has received the message before resolving `channelD.send`'s promise. If the `ack` config is not set to `true` when creating the channel, the promise returned by `channelD.send` will resolve immediately.
### Send messages using REST calls
You can also send a Broadcast message by making an HTTP request to Realtime servers. This is useful when you want to send messages from your server or client without having to first establish a WebSocket connection.
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
queryGroup="language"
>
<TabPanel id="js" label="JavaScript">
<Admonition type="note">
This is currently available only in the Supabase JavaScript client version 2.37.0 and later.
</Admonition>
```js
const channel = supabase.channel('test-channel')
// No need to subscribe to channel
channel
.send({
type: 'broadcast',
event: 'test',
payload: { message: 'Hi' },
})
.then((resp) => console.log(resp))
// Remember to clean up the channel
supabase.removeChannel(channel)
```
</TabPanel>
<TabPanel id="dart" label="Dart">
```dart
// No need to subscribe to channel
final channel = supabase.channel('test-channel');
final res = await channel.sendBroadcastMessage(
event: "test",
payload: {
'message': 'Hi',
},
);
print(res);
```
</TabPanel>
<TabPanel id="swift" label="Swift">
```swift
let myChannel = await supabase.channel("room-2") {
$0.broadcast.acknowledgeBroadcasts = true
}
// No need to subscribe to channel
await myChannel.broadcast(event: "test", message: ["message": "HI"])
```
</TabPanel>
<TabPanel id="kotlin" label="Kotlin">
```kotlin
val myChannel = supabase.channel("room-2") {
broadcast {
acknowledgeBroadcasts = true
}
}
// No need to subscribe to channel
myChannel.broadcast(event = "test", buildJsonObject {
put("message", "Hi")
})
```
</TabPanel>
<TabPanel id="python" label="Python">
Unsupported in Python yet.
</TabPanel>
</Tabs>