Discord JDA EmbedMessage Profile Link - java

Currently I'm making a rather simple logging bot for Discord. All it does is send an EmbedMessage to any #log channel in the server.
This little bit of messy code:
#Override
public void onMessageReceived(MessageReceivedEvent e) {
Message message = e.getMessage();
User author = e.getAuthor();
MessageChannel channel = e.getChannel();
if (channel.getName().equalsIgnoreCase("log") && !author.isBot()) {
message.delete().queue();
} else {
EmbedBuilder eBuilder = new EmbedBuilder();
String aMention = "#" + author.getName() + "#" + author.getDiscriminator();
eBuilder.setAuthor(aMention, null, author.getEffectiveAvatarUrl());
eBuilder.setColor(Color.GRAY);
eBuilder.setFooter("#" + channel.getName(), null);
eBuilder.appendDescription(message.getContentDisplay());
MessageEmbed embed = eBuilder.build();
for (MessageChannel mc : e.getGuild().getTextChannels()) {
if (mc.getName().equalsIgnoreCase("log") && !author.isBot()) {
mc.sendMessage(embed).queue();
}
}
}
}
is the setup for logging non-bot chatting. Currently, it doesn't seem to setup a direct profile link to the user talking, in the line String aMention = "#" + author.getName() + "#" + author.getDiscriminator();. I tried searching for a specific method that gets a profile link, but currently I am not able to find it.

If you want to mention a member, just use:
Member yourMember = e.getMember();
String mention = yourMember.getAsMention();
// ...your code

Related

Akka references increasing constantly with Play Framework

I have changed all my multi-thread actions in my application to Akka a few weeks ago.
However, since it seems that I am starting to run out of Heap space (after a week or so).
By basically looking at all actors with
ActorSelection selection = getContext().actorSelection("/*");
the number of actors seems to increase all the time. After an hour of running I have more then 2200. They are called like:
akka://application/user/$Aic
akka://application/user/$Alb
akka://application/user/$Alc
akka://application/user/$Am
akka://application/user/$Amb
I also noticed that when opening websockets (and closing them) there are these:
akka://application/system/Materializers/StreamSupervisor-2/flow-21-0-unnamed
akka://application/system/Materializers/StreamSupervisor-2/flow-2-0-unnamed
akka://application/system/Materializers/StreamSupervisor-2/flow-27-0-unnamed
akka://application/system/Materializers/StreamSupervisor-2/flow-23-0-unnamed
Is there something specific that I need to do to close them and let them be cleaned?
I am not sure the memory issue is related, but the fact that there seem so many after an hour on the production server it could be.
[EDIT: added the code to analyse/count the actors]
public class RetrieveActors extends AbstractActor {
private String identifyId;
private List<String> list;
public RetrieveActors(String identifyId) {
Logger.debug("Actor retriever identity: " + identifyId);
this.identifyId = identifyId;
}
#Override
public Receive createReceive() {
Logger.info("RetrieveActors");
return receiveBuilder()
.match(String.class, request -> {
//Logger.info("Message: " + request + " " + new Date());
if(request.equalsIgnoreCase("run")) {
list = new ArrayList<>();
ActorSelection selection = getContext().actorSelection("/*");
selection.tell(new Identify(identifyId), getSelf());
//ask(selection, new Identify(identifyId), 1000).thenApply(response -> (Object) response).toCompletableFuture().get();
} else if(request.equalsIgnoreCase("result")) {
//Logger.debug("Run list: " + list + " " + new Date());
sender().tell(list, self());
} else {
sender().tell("Wrong command: " + request, self());
}
}).match(ActorIdentity.class, identity -> {
if (identity.correlationId().equals(identifyId)) {
ActorRef ref = identity.getActorRef().orElse(null);
if (ref != null) { // to avoid NullPointerExceptions
// Log or store the identity of the actor who replied
//Logger.info("The actor " + ref.path().toString() + " exists and has replied!");
list.add(ref.path().toString());
// We want to discover all children of the received actor (recursive traversal)
ActorSelection selection = getContext().actorSelection(ref.path().toString() + "/*");
selection.tell(new Identify(identifyId), getSelf());
}
}
sender().tell(list.toString(), self());
}).build();
}
}

Softlayer - list of servers which are powered on

The following java code lists all the bare metal servers in softlayer for a specific SL account and filters for servers which are powered on (e.g. powerState='on'.
public void listServers(Account.Service service, ApiClient client) throws Exception {
service.withMask().hardware().fullyQualifiedDomainName().primaryIpAddress();
service.withMask().hardware().hardwareStatus();
service.withMask().hardware().id();
Account account = service.getObject();
//
// list of softlayer servers for the client account
//
for (Hardware hardware : account.getHardware()) {
String hostname = hardware.getFullyQualifiedDomainName();
String hardwareStatus = (hardware.getHardwareStatus() == null) ? null : hardware.getHardwareStatus().getStatus();
Long serverId = hardware.getId();
String powerState = null;
if (serverId != null) {
Hardware.Service hardwareService = Hardware.service(client, serverId);
hardwareService.setMask("mask[serverPowerState");
try {
powerState = hardwareService.getServerPowerState();
} catch (Exception ex) {
System.out.println("Error, cannot get powerState, hostname=" + hostname + ", msg=" + ex.getMessage());
}
}
System.out.println("Hostname=" + hostname + ", hwStatus=" + hardwareStatus + ", powerState=" + powerState);
}
}
Code seems to work, but for at least one of the servers, it fails on the call to hardwareService.getServerPowerState()
"Unable to establish IPMI v2 / RMCP+ session".
Any ideas why this is failing ?

How to wait until processes finish Java AWS Lambda

I want to wait until my processes finish before I return my speechlet response, otherwise it seems to cut my process off and thus, not complete it, I actually believe it may freeze the process, but thats not my desire.
How do I go about waiting?
#Override
public SpeechletResponse onIntent(SpeechletRequestEnvelope<IntentRequest> requestEnvelope) {
IntentRequest request = requestEnvelope.getRequest();
Intent intent = request.getIntent();
String intentName = (intent != null) ? intent.getName() : null;
if (intentName == null) return null;
switch (intentName) {
case IntentTitle.NEW_TICKET:
switch (request.getDialogState()) {
case STARTED:
return Response.getDialogueResponse(intent, true);
case IN_PROGRESS:
return Response.getDialogueResponse(intent, false);
case COMPLETED:
String numberString = intent.getSlot(SlotTitle.ID).getValue();
if (!NumberUtils.isCreatable(numberString)) return Response.ERROR;
Member member = Info.GUILD.getMemberById(numberString);
User sender = UserDB.getUser(member);
CommissionTicket commissionTicket = new CommissionTicket(sender);
commissionTicket.create();
//wait until processes finish before continuing
return Response.NEW_TICKED_CREATED;
}
}
return null;
}
UPDATE:
Had a look at the CloudWatch logs, and well, pretty much what I expected was happening is happening... have a look at the times for these logs (I ran them 3 different times, so 3 different times are logged, but apart of the same lambda session)
public void create() {
System.out.println("log2");
GuildController guildController = Info.GUILD.getController();
guildController.createTextChannel(ticketType.name().toLowerCase() + "-" + creator.getName() + "-" + id.value()).queue(channel -> {
System.out.println("log3");
ChannelManager channelManager = channel.getManager();
GuildManager guildManager = channelManager.getGuild().getManager();
List<Member> members = guildManager.getGuild().getMembers();
List<Member> admins = new ArrayList<>();
for (Member member : members) {
for (Role role : member.getRoles()) {
if (!role.getName().equalsIgnoreCase(Info.ADMIN_STRING)) continue;
admins.add(member);
}
}
System.out.println("log4");
for (Member member : members) {
if (member.equals(creator.getMember())) continue;
channel.createPermissionOverride(member).setDeny(Permission.MESSAGE_READ).queue();
}
System.out.println("log5");
for (Member admin : admins) {
if (admin.equals(creator.getMember())) continue;
channel.createPermissionOverride(admin).setAllow(Permission.MESSAGE_READ).queue();
}
System.out.println("log6");
BotMessage botMessage = new BotMessage();
botMessage
.setTitle("New Ticket! User: " + creator.getName())
.setColour(Color.CYAN)
.setDescription("Please enter your full request here! \n" +
"Make sure to let us know whether you are looking for a quote/timeframe,\n" +
"or have a budget in mind, and we will work around you!\n\n" +
"A sales representative will be with you as soon as possible!")
.send((TextChannel) channel);
System.out.println("log7");
this.textChannel = (TextChannel) channel;
TicketDB.addTicket(this);
System.out.println("log8");
}
);
Logs:
https://gyazo.com/0ad2baa8d1438be8364dd1112159c4f4
https://gyazo.com/e197f33335046afe3c9f8f1ace267d30
UPDATE
Implemented the Future class, worked, but still a bit buggy.
It now completely creates the ticket, which is great, however, when I go to send the same call again, it for some reason sends a message in the same channel before preceding to create the next ticket.
So, to simulate...
Function call through AWS Lambda
Creates ticket completely
Function call through AWS Lambda again
Sends a message or two in the previous tickets channel
Creates new ticket completely
https://gyazo.com/dc6e4391f4964f41a73f1c3be92190f9
#Override
public SpeechletResponse onIntent(SpeechletRequestEnvelope<IntentRequest> requestEnvelope) {
IntentRequest request = requestEnvelope.getRequest();
Intent intent = request.getIntent();
String intentName = (intent != null) ? intent.getName() : null;
if (intentName == null) return null;
switch (intentName) {
case IntentTitle.NEW_TICKET:
switch (request.getDialogState()) {
case STARTED:
return Response.getDialogueResponse(intent, true);
case IN_PROGRESS:
return Response.getDialogueResponse(intent, false);
case COMPLETED:
String numberString = intent.getSlot(SlotTitle.ID).getValue();
if (!NumberUtils.isCreatable(numberString)) return Response.ERROR;
Member member = Info.GUILD.getMemberById(numberString);
User sender = UserDB.getUser(member);
System.out.println("log1");
Future<Ticket> commissionTicket = new CommissionTicket(sender).create();
try {
commissionTicket.get(10000, TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrace();
}
//wait until processes finish before continuing
return Response.NEW_TICKED_CREATED;
}
}
return null;
}
In the Ticket class:
public Future<Ticket> create() {
System.out.println("log2");
GuildController guildController = Info.GUILD.getController();
RequestFuture<Channel> channelRequestFuture = guildController.createTextChannel(ticketType.name().toLowerCase() + "-" + creator.getName() + "-" + id.value()).submit();
try {
Channel channel = channelRequestFuture.get(10000, TimeUnit.MILLISECONDS);
System.out.println("log3");
ChannelManager channelManager = channel.getManager();
GuildManager guildManager = channelManager.getGuild().getManager();
List<Member> members = guildManager.getGuild().getMembers();
List<Member> admins = new ArrayList<>();
for (Member member : members) {
for (Role role : member.getRoles()) {
if (!role.getName().equalsIgnoreCase(Info.ADMIN_STRING)) continue;
admins.add(member);
}
}
System.out.println("log4");
for (Member member : members) {
if (member.equals(creator.getMember())) continue;
channel.createPermissionOverride(member).setDeny(Permission.MESSAGE_READ).queue();
}
System.out.println("log5");
for (Member admin : admins) {
if (admin.equals(creator.getMember())) continue;
channel.createPermissionOverride(admin).setAllow(Permission.MESSAGE_READ).queue();
}
System.out.println("log6");
BotMessage botMessage = new BotMessage();
botMessage
.setTitle("New Ticket! User: " + creator.getName())
.setColour(Color.CYAN)
.setDescription("Please enter your full request here! \n" +
"Make sure to let us know whether you are looking for a quote/timeframe,\n" +
"or have a budget in mind, and we will work around you!\n\n" +
"A sales representative will be with you as soon as possible!")
.send((TextChannel) channel);
System.out.println("log7");
this.textChannel = (TextChannel) channel;
TicketDB.addTicket(this);
System.out.println("log8");
Future<Ticket> future = ConcurrentUtils.constantFuture(this);
return future;
} catch (Exception e) {
e.printStackTrace();
}
if (!userIsInTicket(creator)) users.add(creator);
return null;
}
I'm not sure what's going on inside commissionTicket.create(); (I assume it's your code, not part of some library, and that it's running asynchronously somehow), but one solution would be to have that method return a Future<> object and then wait on it to finish. Something along the lines of:
Future<CommissionTicket> commissionTicketFuture = CommissionTicket.create(sender);
commissionTicketFuture.get(SOME_TIMEOUT, TimeUnit.MILLIS);
return Response.NEW_TICKET_CREATED;

How would you make a !!say command for a discord bot?

This is how my commands are set up:
public void onMessageReceived(MessageReceivedEvent evt) {
//Objects
User objUser = evt.getAuthor();
MessageChannel objMsgCh = evt.getChannel();
Message objMsg = evt.getMessage();
//Commands
if(objMsg.getContentRaw().equalsIgnoreCase(Ref.prefix+"say " + message))
{
StringBuilder message = new StringBuilder();
for(int i = 1; i < command.length; i++) {
if(i == command.length-1) {
message.append(command[i]);
}else {
message.append(command[i] + " ");
}
}
objMsgCh.sendMessage(message.toString()).queue();
objMsg.delete();
return;
}
}
It doesn't reply with anything and I don't understand why.
I am using JDA (Java Discord API).
Respect for your creativity but I think you are missing some basic java knowledge. Here is what I think you are aiming for:
public void onMessageReceived(MessageReceivedEvent event){
if(event.getMessage().getContentRaw().startsWith("!!say")){
event.getChannel().sendMessage(event.getMessage().getContentRaw().substring(6)).queue();
event.getMessage().delete().queue();
}
}
I think the if condition is logical. Get the Messages as String in raw format and looking for the string starting with "!!say". Then send a new Message to the channel where the message was received where the message is the raw message as the string with the first five characters (the "!!say") are cut off. So the Bot is repeating the whole message beside the command tag.
Hope this brings you forward in your mission.
I worked out how to do it.
public void onMessageReceived(MessageReceivedEvent evt) {
//Objects
User objUser = evt.getAuthor();
MessageChannel objMsgCh = evt.getChannel();
Message objMsg = evt.getMessage();
if(objMsg.getContentRaw().startsWith(Ref.prefix+"say"))
{
String words = objMsg.getContentRaw().substring(Ref.prefix.length() + 4);
String more_words = words;
objMsgCh.sendMessage(more_words).queue();
You don't really need String more_words = words;
And I do (Ref.prefix.length() + 4) so it says everything after !!say but make sure to make it create something like String prefix = "!!"; because my may not be able to it with the prefix in the if statement. The + 4 counts every just after the prefix and the space between user input.
For Example:
if(objMsg.getContentRaw().startsWith(Ref.prefix+"urban")) {
String query = objMsg.getContentRaw().substring(Ref.prefix.length() + 6);
Because "urban" has 5 characters you would put 6 to account for the space.
Hope that helps.
If you plan on using the JDA-Utilities the following code will work for creating a command.
public class sayCommand extends Command {
public sayCommand() {
this.help = "!say <message>";
this.aliases = new String[] {"!s"};
this.name = "say";
}
#Override
protected void execute(CommandEvent event) {
event.getChannel().sendMessage(event.getMessage().getContentDisplay().split("\\s+", 2)[1]).queue();
}
}
With only using one line, you could have the bot easily mimic your argument.

403 : Daily Limit for Unauthenticated Use Exceeded youtube api v3 java

I Know this question has been asked multiple times, but I couldn't find one working for me.
Basically I am trying to get a youtube video basic info which I get the proper result for that but then when I trigger to get the comments of that video the error pops out saying:
There was a service error: 403 : Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.
My code:
public String getyoutubeitemfull_details(String URI) throws SQLException, IOException{
try {
YouTube youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, new HttpRequestInitializer() {
#Override
public void initialize(HttpRequest request) throws IOException {
}
}).setApplicationName("APP_ID").build();
String apiKey = "API Key";
YouTube.Videos.List listVideosRequest = youtube.videos().list("statistics");
listVideosRequest.setId("qUvPzjSWMSM");
listVideosRequest.setKey(apiKey);
VideoListResponse listResponse = listVideosRequest.execute();
Video video = listResponse.getItems().get(0);
BigInteger viewCount = video.getStatistics().getViewCount();
BigInteger Likes = video.getStatistics().getLikeCount();
BigInteger DisLikes = video.getStatistics().getDislikeCount();
BigInteger Comments = video.getStatistics().getCommentCount();
System.out.println("[View Count] " + viewCount);
System.out.println("[Likes] " + Likes);
System.out.println("[Dislikes] " + DisLikes);
System.out.println("[Comments] " + Comments);
CommentThreadListResponse videoCommentsListResponse = youtube.commentThreads()
.list("snippet").setVideoId("qUvPzjSWMSM").setMaxResults(50l).setTextFormat("plainText").execute();
List<CommentThread> videoComments = videoCommentsListResponse.getItems();
for (CommentThread videoComment : videoComments) {
CommentSnippet snippet = videoComment.getSnippet().getTopLevelComment().getSnippet();
System.out.println(" - Author: " + snippet.getAuthorDisplayName());
System.out.println(" - Comment: " + snippet.getTextDisplay());
System.out.println("\n-------------------------------------------------------------\n");
}
} catch (GoogleJsonResponseException e) {
System.err.println("There was a service error: " + e.getDetails().getCode() + " : "
+ e.getDetails().getMessage());
} catch (IOException e) {
System.err.println("There was an IO error: " + e.getCause() + " : " + e.getMessage());
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
FYI: So much of question that I have been through so far talk about adding listVideosRequest.setKey(apiKey); which I have it done. I also Have enable OAuth 2.0 enabled in my google console.
Thanks to #DalmTo for throwing to its direction.
Basically Api Key doesn't have priviledges to retrieve comments and things like that. for deep priviledges I had to use Oauth, which basically is being created the same was as API Key but in Oauth you receive a client_secrets.json file containing: client secret, client ID and etc...
Then you call that in you code.
Note: Their is verious ways of calling you client_secrets.json file but it depends on your need.
My way: Reader clientSecretReader = new InputStreamReader(
new FileInputStream("/home/Downloads/src/client_secrets.json"));

Categories