I'm using iOS/Swift with Firebase.
My question is simle, how do I observe nested children (without specifying the parent).
To be more specific, I'm building a messages app and when the user sends a message with state Sending, I want the server (for now it's a separate server from Firebase, since I didn't know how to do it without one) to update it to Sent.
In order to do that, I plan on observing my /messages path for any children added, so I can change the state to Sent.
The problem is, my messages are nested, just like with Firebase's example:
"messages": {
"one": {
"m1": {
"state": "Sending",
"message": "Some message",
},
"m2": { ... },
"m3": { ... }
},
"two": { ... },
"three": { ... }
}
Because the rooms (one, two, three) are not always the same, I don't want to observe each one of them, I want to observer something like /messages/*/ for children added.
So any time a message is added (doesn't matter to which room) I want to change it's state from Sending to Sent.
Related
This question already has an answer here:
Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly
(1 answer)
Closed 1 year ago.
I am new to Firebase. The following is my database's structure.
{
"dvdStores": {
"store1": {
"movies": {
"0": "Don't Look Up",
"1": "Top Gun"
}
},
"store2": {
"movies": {
"0": "Jungle Book",
"1": "Taken"
}
},
"store3": {
"movies": {
"0": "The Matrix",
"1": "Home Alone"
}
},
"store4": {
"movies": {
"0": "The Lion King"
}
}
}
}
Can I get all the movies corresponding to multiple keys in a single query?
I would e.g. want to get all the movies corresponding to keys store1 and store4. Can this be done in a single query?
Thanks in advance :)
This is not possible. You must request them each individually. All queries for a node always get the entire node, including all of its nested children. Children cannot be selectively included or excluded.
It's worth noting also that there is not much overhead in making multiple requests. The data for each query is pipelined over a single socket connection, so as long as you keep that connected saturated with requests, you are not losing very much perceived performance.
I am new to Slack APP development, I am developing the app using Slack bolt python. In my app I have configured the slack interaction using the button click, on clicking the button I am calling the corresponding listener(identified by action_id mentioned in the button). In the listener I am getting the block_actions payload which contains all the state values of the event, but in addition to that I want to some arguments to the listener function. Is it possible in any way that we can send additional arguments to the listeners
#app.action("change_time_period")
def handle_change_time_period(ack, context, body, client, logger, message, say):
# want the arguments here such as passing email_id from post_data
def post_data(user_id, email_id):
client = WebClient(token=os.environ.get("SLACK_BOT_TOKEN"))
result = client.chat_postMessage(
channel=user_id,
blocks=[
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"emoji": True,
"text": "Change time period"
},
"style": "primary",
"value": "time_period",
"action_id": "change_time_period"
}
]
}
]
)
In the code above, I will be calling the post_data which will post the message containing the block kit, once the user clicks the button the handle_change_time_period will be called
Slack block kit buttons do not have a field where we can pass metadata to the interactivity handler. One workaround to achieve this would be to make use of the value field of the button element dict to dump a JSON with the required data. From the Slack API doc, the value field can hold a maximum of 2000 characters. Your value field can be something like
"value": json.dumps({"actual_value" : "time_period", "email" : "johndoe#abc.com"})
This can be optimized further by reducing the characters in keys. If the extra data you need to pass goes beyond the char limit, you might have to consider caching the data on the server and passing a cache key in the block which can then be used in handler to retrieve the actual data from the cache.
I have List of objects in firebase DB. how to get specific child who changed in the list?
Do I have made connection with every child?
Actually yes you have to do that. If you e.g. have users in there, you'll end up with something like this:
{
users: {
"user-0": {
"firstName": "Max",
"lastName": "Powers"
},
"user-1": {
"firstName": "Maxime",
"lastName": "Powers"
}
}
}
Now, from your apps perspective, the user is signed in and therefore the app knows the user-id. With this information you can subscribe to changes on the whole user.
If you go one step further and nest e.g. rides below each user, as a mobility app will do, you end up with a JSON like this:
{
users: {
"user-0": {
"rides": {
"ride-0": {
"updated_at": ...
}
}
}
}
}
When in this mobility app a user creates a ride, the app will will receive a ride-id from the backend which it can use to subscribe to the related ride in firebase. The path would be e.g. users/<user-id>/rides/<ride-id>. The app will then get updates each time this ride is updted in the realtime database.
In the end each user has multiple subscriptions. We do it for a couple of years this way and it works quite well 👍
This is a rough example of what my database looks like.
"userA": {
"uf": {
"userB": "0"
}
},
"users": {
"userA": "0",
"userB": "0",
"userC": "0"
}
And this is a rough example of the rule I am trying to write.
//USER ID
"$uid": {
//USER FRIENDS
"uf": {
//FRIEND USER ID
"$fuid": {
".write": "$uid === auth.uid &&
root.child('users').hasChild($fuid)",
}
},
},
And this is what I am trying to get working in the simulator
//Location /userA/uf/
//Data { "userC": "0" }
It seems that the security rule will always deny a write when the "key" for a data key value pair is a variable in my rules, in this case "$fuid". The simulator will return the messages "Simulated set denied" and "Write denied" but won't give me any additional details. I could get around this by writing the following.
//Simulation Method set
//Location /userA/uf/userC/
//Data { "0": "0" }
But this feels like it's writing unnecessary data to my database. What is the best practice here? Thanks.
Your rules give access to {uid}/uf/{fuid} but you're trying to write at {uid}/uf.
That {"0": "0"} is indeed unnecessary, you can just write "0".
If you want to write multiple friends at once, you can perform a multipath update, or modify your rules to allow writing directly at {uid}/uf and ".validate" the children.
Side note: if your users can be deleted, if user A has user B as a friend and user B is deleted, your rules won't allow user A to remove user B from the friends list. You should take care of that by changing the rules to allow the deletion of friends that do not exist, or by setting up an onDelete() triggered cloud function that would do the cleanup.
I'm using slacks events API and have setup a subscription to the reactions_added event. Now when a reaction is added to a message, slack will send me a post body with all the details of the dispatched event as described here.
The problem I'm having is that I want to get the details, specifically the text of the message that my users have reacted to so I can parse/store etc that specific message. I assumed the message would return with some type of UUID that I could then respond to the callback and get the text, however I'm find it difficult to get the specific message.
The only endpoint I see available is the channels.history, which doesn't seem to give me the granularity I'm looking for.
So the tl;dr is: How do I look up a via slacks API, a messages text sent from the events API? Give the information I have the event_ts, channel and message ts I thought would be enough. I'm using the ruby slack-api gem FWIW.
You can indeed use the method channels.history (https://api.slack.com/methods/channels.history) to retrieve message from a public channel . The reaction_added dispatched event includes the channel ID and timestamp of the original message (in the item) and the combination of channelId + timestamp should be unique.
Be careful that you use the correct timestamp though. You need to use item.ts not event_ts
Full example dispatched event from the docs:
{
"token": "z26uFbvR1xHJEdHE1OQiO6t8",
"team_id": "T061EG9RZ",
"api_app_id": "A0FFV41KK",
"event": {
"type": "reaction_added",
"user": "U061F1EUR",
"item": {
"type": "message",
"channel": "C061EG9SL",
"ts": "1464196127.000002"
},
"reaction": "slightly_smiling_face"
},
"event_ts": "1465244570.336841",
"type": "event_callback",
"authed_users": [
"U061F7AUR"
]}
So calling channels.history with these values set should work:
latest = item.ts value
oldest = item.ts value
inclusive = 1
channel = item.channel value
If you want to get messages from a private channel you need to use groups.history.
https://api.slack.com/methods/channels.history