The server I am operating is being used to generate Firebase tokens and to read and write values from firebase, I use REST APIs with a different type of token which has different UID prefix.
However, since many features have been added to the server, I decided to use Firebase java library and now migrating the previous code that was written for REST APIs.
The question is, how can I use Firebase Java library with tokens omitting authentication process?
Authentication process runs asynchronously so it can be applied to client application but not to server.
What if it fails authentication? or what if it takes too much time?
The previous code just used auth token for every request like this:
https://abcd.firebaseio.com/ns/blahblah/event?auth=token
So it doesn't need any authentication process.
Hope you understand my poor English.
Thanks!
According to the Firebase documentation for authentication server-side processes, there are three ways to authenticate:
Using a Firebase app secret
Using a secure JWT with the optional admin claim set to true
Using a secure JWT designed to give access to only the pieces of data a server needs to touch
You are currently getting a secure JWT from your authentication server, so you are using option 2 or 3.
The alternative is to use the so-called app secret of you Firebase application. You can find this value in the Dashboard of the application and it can serve as a drop-in replacement for the current token.
However I highly recommend against this approach. Jenny wrote up a pretty exhaustive list of reasons against it here: https://stackoverflow.com/a/29240941
You can't replace the whole authentication process with just a secret using the Java Client Library. You need to generate a JWT. Authentication lasts for 24 hours, so you can save the generated JWT until it fails, or you just authenticate again prior to 24 hours, and keep that JWT again.
In order to handle the fact that authentication is an asynchronous process you'd also have to use a CountdownLatch or a Semaphore to prevent your program from exiting before the authentication process receives a response from Firebase.
CountdownLatch
A synchronisation aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
import com.firebase.client.AuthData;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.security.token.TokenGenerator;
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) {
Map<String, Object> payload = new HashMap<String, Object>();
payload.put("uid", "uniqueId1");
payload.put("some", "arbitrary");
payload.put("data", "here");
TokenGenerator tokenGenerator = new TokenGenerator("<YOUR_FIREBASE_SECRET>");
String token = tokenGenerator.createToken(payload);
Firebase fb = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
CountDownLatch done = new CountDownLatch(1);
fb.authWithCustomToken(token, new Firebase.AuthResultHandler() {
#Override
public void onAuthenticationError(FirebaseError error) {
System.err.println("Login Failed! " + error.getMessage());
done.countDown();
}
#Override
public void onAuthenticated(AuthData authData) {
System.out.println("Login Succeeded!");
// Save your JWT to keep using it for 24 hours
done.countDown();
}
});
done.await();
}
}
Semaphore
It is used to control the number of concurrent threads that are using a resource. You could think of it as tickets to use a resource. You set the number of tickets available when you create it, and when acquire() is called with no tickets left, your process will wait for one to become available (on a release() call). On this code it is being created with zero "tickets" available:
import com.firebase.client.AuthData;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.security.token.TokenGenerator;
import java.util.concurrent.Semaphore;
public class Main {
public static void main(String[] args) {
Map<String, Object> payload = new HashMap<String, Object>();
payload.put("uid", "uniqueId1");
payload.put("some", "arbitrary");
payload.put("data", "here");
TokenGenerator tokenGenerator = new TokenGenerator("<YOUR_FIREBASE_SECRET>");
String token = tokenGenerator.createToken(payload);
Firebase fb = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
Semaphore semaphore = new Semaphore(0);
fb.authWithCustomToken(token, new Firebase.AuthResultHandler() {
#Override
public void onAuthenticationError(FirebaseError error) {
System.err.println("Login Failed! " + error.getMessage());
semaphore.release();
}
#Override
public void onAuthenticated(AuthData authData) {
System.out.println("Login Succeeded!");
// Save your JWT to keep using it for 24 hours
semaphore.release();
}
});
semaphore.acquire();
}
}
Related
I am coding a feedback feature in my Discord Bot, when someone leaves, they should be DMed a message asking why they left.
event.getUser().openPrivateChannel()
.flatMap(channel -> channel.sendMessage("Hello, we are sorry you're leaving "+event.getGuild().getName()+", if you don't mind, please tell us why you left or leave any other feedback here, it'll help us improve the server and improve experience for you if you re-join again in the future.\n\nThank you ❤."))
.queue();
The code above is responsible for sending it, I tried to create a state machine in a private channel but it didn't work:
import bot.Main;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
public class Feedback extends ListenerAdapter {
private final long channelId, authorId;
public Feedback(MessageChannel channel, User author) {
this.channelId = channel.getIdLong();
this.authorId = author.getIdLong();
}
#Override
public void onMessageReceived(MessageReceivedEvent event) {
if (event.getAuthor().isBot()) return;
if (event.getAuthor().getIdLong() != authorId) return;
if (event.getChannel().getIdLong() != channelId) return;
MessageChannel channel = event.getChannel();
String content = event.getMessage().getContentRaw();
event.getChannel().sendMessage("Thanks for your feedback!").queue();
EmbedBuilder feedback = new EmbedBuilder();
feedback.setTitle("Automated System Operations - Leaving Feedback");
feedback.addField("Feedback", content, false);
feedback.setColor(0xC90004);
feedback.setAuthor(event.getAuthor().getAsTag()+" - "+event.getAuthor().getId(), "https://support.discord.com/hc/en-us/articles/209572128-How-do-I-log-out-", event.getAuthor().getAvatarUrl());
feedback.setImage("https://media.discordapp.net/attachments/894913784823566428/896323821336948736/unknown.png?width=384&height=192");
Main.jda.getGuildById("894913620868202506").getTextChannelById("896322509874540545").sendMessage(feedback.build()).queue();
}
}
I got this event state-machine channel but I don't know how to addListener to it in DMs.
Any help is accepted <3
You can add the state machine event listener with JDA#addEventListener:
event.getUser().openPrivateChannel().flatMap(channel -> {
event.getJDA().addEventListener(new Feedback(channel, event.getUser()));
return channel.sendMessage("hello");
}).queue();
I would recommend to remove your event listener after you received that response with event.getJDA().removeEventListener(this);
You never have to guess how to use a library - that's what documentation is for. Any library worth its salt has documentation listing every single class, method, and the property you need to worry about.
A quick google search for "discord-jda docs" takes us to the JavaDoc: https://ci.dv8tion.net/job/JDA/javadoc/index.html
You want to send a message to a user, right? So let's use the search bar and find User. First result under Types is net.dv8tion.jda.API.entities.User. We're now at https://ci.dv8tion.net/job/JDA/javadoc/net/dv8tion/jda/api/entities/User.html
If you want to know how to do something with a user, we look at the Methods every User has. Two catch my eye right away: User.hasPrivateChannel() and User.openPrivateChannel(). We'll click the second one since it looks relevant.
Lo and behold, the docs have example usage! I'll quote it below:
// Send message without response handling
public void sendMessage(User user, String content) {
user.openPrivateChannel()
.flatMap(channel -> channel.sendMessage(content))
.queue();
}
This seems pretty straightforward. So the basic usage you're looking for (assuming event is a MessageReceivedEvent) is this:
event.getAuthor().openPrivateChannel().flatMap(channel -> channel.sendMessage("hello")).queue();
is it possible to make a system SMS Based Query in Java?because im planning to try and make a System Based on java that has SMS Based query like when you send some sort of code to the system it replies also with a sms
Yes, check out twilio. Pretty great and can set up a cool chat bot type of thing either using some web server or amazon lambda. You can set a script so it will take certain inputs, do whatever code you want and send an output.
// Install the Java helper library from twilio.com/docs/java/install
import com.twilio.Twilio;
import com.twilio.rest.api.v2010.account.Message;
import com.twilio.type.PhoneNumber;
import java.net.URISyntaxException;
public class SmsSender {
// Find your Account Sid and Auth Token at twilio.com/console
public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
public static final String AUTH_TOKEN = "your_auth_token";
public static void main(String[] args) throws URISyntaxException {
Twilio.init(ACCOUNT_SID, AUTH_TOKEN);
Message message = Message
.creator(new PhoneNumber("+14159352345"), // to
new PhoneNumber("+14158141829"), // from
"Where's Wallace?")
.create();
}
}
I'm in the middle of creating an application for Wear that has a phone companion app to do some of the heavier processes and make API calls.
So far in regards to communication between the two devices, I have been following this tutorial - http://android-wear-docs.readthedocs.io/en/latest/data.html
This has left me with the phone being able to communicate with the watch, but now I'm wondering how I replicate it working the other way.
The current code I have on the Wear app is like this (a seperate listener class is also present on the phone and watch):
public void sendTestMessage(View view)
{
String WEARABLE_DATA_PATH = "/wearable_data";
DataMap dataMap = new DataMap();
dataMap.putString("WATCH2PHONE TEST MESSAGE EVENT!", "1");
new SendToDataLayerThread(WEARABLE_DATA_PATH, dataMap).start();
}
class SendToDataLayerThread extends Thread
{
String path;
DataMap dataMap;
SendToDataLayerThread(String p, DataMap data)
{
path = p;
dataMap = data;
}
public void run()
{
PutDataMapRequest putDMR = PutDataMapRequest.create(path);
putDMR.getDataMap().putAll(dataMap);
PutDataRequest request = putDMR.asPutDataRequest();
DataApi.DataItemResult result = Wearable.DataApi.putDataItem(googleClient, request).await();
if (result.getStatus().isSuccess())
{
Log.v("myTag", "DataMap: " + dataMap + " sent successfully to data layer ");
}
else
{
Log.v("myTag", "ERROR: failed to send DataMap to data layer");
}
}
}
Listener Class (for watch, the phone version is identical):
public class ListenerService extends WearableListenerService
{
#Override
public void onDataChanged(DataEventBuffer dataEvents)
{
DataMap dataMap;
for (DataEvent event : dataEvents)
{
Log.v("myTag", "DataMap received on device: " + DataMapItem.fromDataItem(event.getDataItem()).getDataMap());
}
}
}
So sending the test message sends the messages to the layer and they send, but are received by the watch's listener service.
I'm assuming the "String WEARABLE_DATA_PATH = "/wearable_data";" is what's causing it to end up being received by the watch but I'm unsure what to change it to in order to get it to send properly.
The Data API works the same in both directions. The specific architecture to use on the handheld depends on your app's structure, but there is a good overview of the options in the documentation at https://developer.android.com/training/wearables/data-layer/events.html#Listen.
That page also discusses using a path to filter the data events received. Again, this depends on your architecture, but it might be reasonable to use paths like "/data_from_handheld" and "/data_from_wearable" to differentiate the DataItems going in the different directions. Or you can use the same path, and then the data events will appear on all connected devices - which may or may not be what you want.
One other common "gotcha": Data API events only fire when the data has actually changed. This is an efficient way for the API to handle real-world communications, but can make development difficult. To force it, simply include an item that is always different, such as:
dataMap.putLong("timestamp", System.nanoTime());
...but be sure to take that out before deploying the app!
I need to implement front-end for Server-Sent-Event. I use GWT, and i can not find any solution to create a listener for SSE. I need to push the data from server and to receive it on client every time hen data was changed. So for now i have a something like this:
private void method() {
final EventSource eventSource = EventSource.newEventSourceIfSupported();
if (null != eventSource) {
eventSource.setListener(this);
eventSource.open(GWT.getHostPageBaseURL() + "rest/myresource");
}
}
#Override
public void onOpen(EventSource eventSource) {
Window.alert("Open");
}
#Override
public void onClose(EventSource eventSource) {
Window.alert("onClose");
}
#Override
public void onMessage(EventSource eventSource, String lastEventId, String type, String data) {
Window.alert("lastEventId: " + lastEventId);
Window.alert("type: " + type);
Window.alert("data: " + data);
}
#Override
public void onError(EventSource eventSource) {
Window.alert("onError");
}
my class implements EventSourceListener
But it does not work. Actually this code reacting only when connection is opened, but it is impossible to receive any message from server. Do somebody know how to deal the issue with receiving data on client using GWT?
There are so many methods exist in GWT for push back services like a GWT Event Services enter link description here
In order for the server to initiate a request to the client, you will need to use WebSockets, and experimental HTML5 feature currently only supported by Chrome.
Or, to simulate this kind of interaction, you can use Comet (long-polling), made available in GWT by the rocket-gwt project.
Here is my code:
import winterwell.jtwitter.Twitter;
import winterwell.jtwitter.*;
import java.util.List;
public class twitterbagla {
private static final String username="blabla";
private static final String password="xx";
public static void main(String[] args) {
Twitter twitter=new Twitter (username,password);
System.out.println(twitter.getStatus("hah"));
//System.out.println(twitter.getFollowers());
twitter.setStatus("hello world something");
List<User> followers=twitter.getFollowers();
for(User user : followers){
System.out.println(user.getName());
}
}
}
and here is console
It's amazing to me that the best things in life are steps forward that come with negative assumptions.
Exception in thread "main" winterwell.jtwitter.TwitterException$UpdateToOAuth: You need to switch to OAuth. Twitter no longer support basic authentication.
at winterwell.jtwitter.URLConnectionHttpClient.processError(URLConnectionHttpClient.java:369)
at winterwell.jtwitter.URLConnectionHttpClient.post2(URLConnectionHttpClient.java:303)
at winterwell.jtwitter.URLConnectionHttpClient.post(URLConnectionHttpClient.java:272)
at winterwell.jtwitter.Twitter.updateStatus(Twitter.java:2593)
at winterwell.jtwitter.Twitter.updateStatus(Twitter.java:2519)
at winterwell.jtwitter.Twitter.setStatus(Twitter.java:2291)
at twitterbagla.main(twitterbagla.java:16)
https://dev.twitter.com/docs/twitter-libraries#java You can find some libraries here..
See the documentation at http://www.winterwell.com/software/jtwitter.php
You want to create an OAuthSignpostClient. There's then an authorisation step with Twitter (you can store the resulting tokens to reuse later).
Then use new Twitter(name, oauthClient) to create your Twitter instance.