Is it possible to get the username from the user that pressed my inlinebutton? - telegram

I'm trying ot create a bot that make a list of people that want to join my lessons.
As they press join i want to update the message with their username but I'm struggling to find the right way.
The only thing I found is using Aiogram's User class, but it seems not the right choice.
#dp.message_handler(commands=['lessons'])
async def random_answer(message: types.Message):
await message.reply("...", reply_markup=keyboard_inline)
#dp.callback_query_handler(text=["09:30", "18:00", "19:00", "20:00"])
async def random_value(call: types.CallbackQuery,
line1="Lessons\n\n09:30\n\n\n18:00\n\n\n19:00\n\n\n20:00\n\n"):
if call.data == "09:30":
await call.message.edit_text(line1[:13]+str(types.User.full_name)+line1[13:],
reply_markup=keyboard_inline)

Related

voice call with agora and firebase flutter

I'm trying to implement voice call functions in my app using agora and firebase where the user can make one to one calls but here in this join function I pass the channel name which is the same for both users in firebase
but I don't know what to pass in the optionalUid which uid is this? and the token in agora require a channel name to generate one but I don't want to type a specific channel name in the console what should I do?
_joinChannel() async {
await Permission.microphone.request();
await _engine
.joinChannel(null, widget.call.channelName!, null,
optionalUid)
.catchError((onError) {
print('error ${onError.toString()}');
});}
If the optionalUid is not set, or set to 0 it will automatically create one for you.
You can read about it more here: https://docs.agora.io/en/Voice/API%20Reference/flutter/v4.0.5/agora_rtc_engine/RtcEngine/joinChannel.html

Changing display name takes too long. Flutter and FIrebase

I'm trying to make a list of my users and the display name takes a bit to change after update profile but by that time the list already has a null in the name section.
final User user = (await
_auth.createUserWithEmailAndPassword(
email: emailR,
password: passwordR,
)
).user;
user.updateProfile(displayName: usernameR);
emailc.clear();
passwordc.clear();
usernamec.clear();
DateTime now = DateTime.now();
String dt = "${now.day.toString().padLeft(2,'0')}/${now.month.toString().padLeft(2,'0')}/${now.year.toString()} ${now.hour.toString()}:${now.minute.toString()}";
FirebaseFirestore.instance.collection("users").doc(user.uid).set({
"id": user.uid,
"name": user.displayName,
"email": user.email,
"created_at": dt,
});
The reason why I think its a timing problem is because on my main page where it says the username the first time when I register, it'll show "hey, null" and every time after that it'll show the correct username.
The updateProfile call is an asynchronous operation, and user.displayName won't be updated until that operation has completed. Luckily it returns a Future, so you can just use await on the call to wait for it to complete, in the same way you already do for createUserWithEmailAndPassword.
So:
await user.updateProfile(displayName: usernameR);
bro its problem you fetching and send data every things takes time so for this purpose you need to use circularprogress indicator its take 1 or 2 second bro first its change your name in firstore and then its fetch from firestore so avoid from this use Circularprogress indictor when your name is null.hope you will like my sugestion

How to disconnect a discord bot from voice channel after user left?

I would like to add an event that my music bot leaves the voice channel immediately if the user leaves while the song is still playing. If there are multiple users in the channel, the bot should of course stay in the channel. I only have one approach there, but would need help. I would try the following:
async def check_member(self, ctx):
channel = ctx.author.voice.channel
member_count = len(voice_channel.members)
if member_count == 1:
await channel.disconnect
but somehow this doesn't seem to work.
I know for fact that there is a similar post but this did not work for me too as I defined some things different.
My second attempt was:
async def check_member(self, ctx):
channel = ctx.author.voice.channel
member_count = len(channel.members)
client = ctx.guild.voice_client
if member_count == 1:
await client.disconnect()
(Did not work either.)
To define does not work: I build the function in a different way now:
#tasks.loop(seconds=2)
async def check(self, ctx):
voice_channel = ctx.author.voice.channel
member_count = len(voice_channel.members)
client = ctx.guild.voice_client
if member_count == 1:
await client.disconnect()
This is now a total different count. What I am trying to do is loop the commands.Cog.listener() function every 2 seconds. For tests I played a song and left instantly after the bot started playing. I thought the bot would leave the channel too but it did not. There was no output in my log that I defined something wrong.
A loop is kinda unefficient, you can simply use the on_voice_state_update event
async def on_voice_state_update(member, before, after):
voice_state = member.guild.voice_client
# Checking if the bot is connected to a channel and if there is only 1 member connected to it (the bot itself)
if voice_state is not None and len(voice_state.channel.members) == 1:
# You should also check if the song is still playing
await voice_state.disconnect()
Reference:
on_voice_state_update

How to Update data for FirebaseUser Stream when Email is Verified (Flutter)

I'm building a flutter app with firebase auth dealing with users. My goal is to streamline the user onboarding experience by allowing email sign up and verification without forcing the user to sign out and sign in again to use the full features. Before testing with real users, this is exactly what I had configured but the overwhelming feedback is that it interrupts and may even cause the user to abandon the authentication flow altogether; the app should simply detect this change in verification status without having to log out.
WHAT I'VE TRIED
I'm using the following in main.dart to provide auth state throughout the app:
StreamProvider < FirebaseUser > .value(
value: FirebaseAuth.instance.onAuthStateChanged,
),
I extract it with
user1 = Provider.of<FirebaseUser>(context, listen: true);
in the individual pages and access different properties like user1.isEmailVerified in ternary expressions to determine what is displayed to the user.
I know that onAuthStateChanged doesn't get called for changes in email verification, only for user sign in and sign out as explained in the accepted answer for this question, but I still need to update the user value that determines the UI shown when a user verifies their email. I have chosen to use a button "complete email verification" which will manually trigger the check and reload of the user profile with the new value once verified. This is the code for that button:
() async {
// 1
FirebaseUser user =
await _firebaseAuth.currentUser();
print(user.isEmailVerified); // returns false
// 2
await user.getIdToken();
print(user.isEmailVerified);// returns false
// 3
await user.reload();
print(user.isEmailVerified);// returns false
//4
user = await _firebaseAuth.currentUser();
print(user.isEmailVerified);// this finally returns true
}
where final _firebaseAuth = FirebaseAuth.instance;
I've noticed that calling .currentUser() twice (before and after reload()) is the only way to actually return true for the .isEmailVerified property without logging out and back in. This is an answer I found in this GitHub thread.
If I press the button again, all the print statements above return true.
THE PROBLEM
That's great, but the problem is the user1 variable that stores the FirebaseUser stream does not change or update even after this, so the UI remains the same despite the user email being verified. I know this because I've placed the following checks in the code:
print('this one is from the stream:');
print(user1.isEmailVerified);
It still returns false even when in the button function body, the user.isEmailVerified returns true.
I've tried calling set state within the button like this:
setState(() {user1 = user; });
But it seems that the value of user1 still remains the same and still returns false for the user1.isEmailVerified, even though I'm trying to set it to the new value derived from the button's function!
This is really frustrating as I feel I'm very close but I just don't know how to refresh the value of the user1 (firebase user stream) throughout the app or even just on that one screen. This should be more straightforward.
I've noticed that pressing hot reload after verifying the email and pressing the button above will automatically show the updated .isEmailVerified value throughout the app while debugging on flutter. Is there a way to programmatically trigger the same kind of rebuild that hot reload uses that will also refresh the firebase user stream data WITHOUT having to log out and sign back in? Maybe this is where the answer lies, but I don't know how to proceed with that.
Any help would be appreciated.
Instead of onAuthStateChanged, you can use userChanges stream which
provides events on all user changes, such as when credentials are linked, unlinked and when updates to the user profile are made. The purpose of this Stream is to for listening to realtime updates to the user without manually having to call [reload]
see https://firebase.flutter.dev/docs/auth/usage/#authentication-state
I was also facing this problem and get fixed with the help of:
await user.reload();
user = await _auth.currentUser();
user.isEmailVerified => now it is true
I came across your question while trying to figure out why user.reload() wasn't updating the email verification status of my user. Thank you for suggesting getting currentUser again, which works.
To answer your question, I use a BehaviorSubject from rxdart to store my FirebaseUser, so I can get notifications of the user changing from anywhere in the app with a StreamBuilder:
final BehaviorSubject<FirebaseUser> firebaseUser = new BehaviorSubject<FirebaseUser>();
userListener = FirebaseAuth.instance.onAuthStateChanged.listen((user) {
if (user == null) {
userSignedOut();
}
else if (currentFirebaseUser == null || user.uid != currentFirebaseUser.uid) {
processNewUser(user);
}
firebaseUser.add(user);
});
Auth state change listener didn't work for me. Field isEmailVerified remains false even after user verifies his email.
My workaround:
Started from the assumption that user leaves the app to verify his email (which mean app is paused), and he returns to the app after verifying it (app resumes).
What I did was attach a WidgetsBinding to a relevant stateful widget where I wanted to display if email was verified (but can be done elsewhere). This involves two steps.
First step is to attach the binding:
#override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
}
#override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
Second step is to override the didChangeAppLifecycleState to reload the user. I created a function that does the reload and sets a new firebaseUser object
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed && !firebaseUser.isEmailVerified)
refreshFirebaseUser().then((value) => setState(() {}));
super.didChangeAppLifecycleState(state);
}
Future<void> refreshFirebaseUser() async {
await firebaseUser.reload();
firebaseUser = FirebaseAuth.instance.currentUser;
}
So what this is basically doing is to reload firebase user object everytime the user returns to the app, while its email is not verified. This seems cleaner than the best workaround that I've found in SO which consisted in setting and cancelling a recurrent action through a timer.
The FirebaseAuth Flutter plugin provides a Stream with
onAuthStateChanged, which is useful for getting updates when a user
signs-in or signs-out, but it fails to provide an update when the user
data itself changes. A common problem is when we want to detect if the
user has just verified his e-mail address, in other words get if
FirebaseUser.isEmailVerified changed its value, as this is updated
server-side and not pushed to the app.
FirebaseAuth.currentUser() will only detect changes made locally to
the user, but if any changes are made server-side, it won't detect,
unless FirebaseUser.reload() is called first and then we need to call
FirebaseAuth.currentUser() again to get the reloaded user, but still
this user won't be emitted by onAuthStateChanged.
This can help you:
https://pub.dev/packages/firebase_user_stream
You will find a manual solution or you can use the package.

Flutter - How to add Firebase-Auth user credentials to new records (FireStore documents)?

I'm trying to create a simple Crud app with Flutter and Firebase which the records (documents created in FireStore) are related to the user who has been Authenticated. Therefore the Crud functions will only be performed by the user who created the record. IE a user will only be able able to edit/update/delete the records they added in the first place.
I have the firebase_auth and crud functions working nicely with firestore. the issues i'm have is with relating the two. I have chosen to use the users email and the unique identifier (i'm not sure if it's better to use the auto generated user id or not). I have created a separate function for simply returning the current user's email as it's being added to the firestore document. The problem is the first time i add a record the user email returns null, If i submit the form again it starts working fine.
String _userEmail;
_getUserAuthEmail() {
FirebaseAuth.instance.currentUser().then((user){
setState((){this._userEmail = user.email;});
});
return this._userEmail;
}
Which is being called from the onPressed event
onPressed: () {
crudObj.addData({
'itemName': this.itemName,
'userEmail': _getUserAuthEmail(),
}).then((result) {
dialogTrigger(context);
}).catchError((e) {
print(e);
});
},
As i'm just starting out please let me know if there is a better approach. Cheers.
You are getting null because you are not waiting for the currentUser method to settle. Change the _getUserEmail method like this:
String _userEmail;
_getUserAuthEmail() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
setState(() {
_userEmail = user.email;
});
return this._userEmail;
}
Also, about this
"I have chosen to use the users email and the unique identifier (i'm not sure if it's better to use the auto generated user id or not)."
I suggest you using the user's uid for saving user related stuff.

Resources