I Programmed an Discord Bot to make an Time Role (a Role that Changes its name every second to: "{UserName} --D --H --min --sec).
It worked Fine, but after an hour it does not worked anymore, but I did not change anything in the Code.
I have an Command ("{prefix} shutdown"), it basicly do ShardManager.shutdown(); and than I get an error.
Code for the Command:
package Discord.Commands.TimeRank;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy;
import Discord.Bot;
import Discord.Commands.Command;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.exceptions.RateLimitedException;
public class startTimeRole extends Command {
public static Server server;
public Timer timer;
public static boolean isRunning = false;
#Override
public void set(String prefix, String help) {
prefix = "timeRole";
help = Bot.prefix + " timeRole <STATE> -> STATE = start, pause";
super.set(prefix, help);
}
#Override
public void Execute(MessageReceivedEvent event, String[] args) {
super.Execute(event, args);
server = server.get(event.getGuild());
if (args.length <= 1) {
event.getTextChannel().sendMessage("Please give at least one **Argument**!").queue();
help(event);
return;
} else {
if (args[1].equals("start")) {
if (!isRunning) {
timer = new Timer();
event.getTextChannel().sendMessage("Activated timeRole!").queue();
isRunning = true;
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
for (Client client : server.onlineClients) {
Role timeRole = null;
for (Role role : client.member.getRoles()) {
if (timeRole != null) {
break;
}
if (role.getName().startsWith(client.member.getUser().getName())) {
client.onlineTime.setTime(role.getName().substring(client.member.getUser().getName().length() + 1));
client.onlineTime.plus(10);
timeRole = role;
}
}
if (timeRole != null) {
timeRole.getManager()
.setName(client.member.getUser().getName() + " " + client.onlineTime.get())
.queue();
} else {
try {
server.guild
.addRoleToMember(client.member,
server.guild.createRole()
.setName(client.member.getUser().getName() + " "
+ client.onlineTime.get())
.complete(true))
.queue();
} catch (RateLimitedException e) {
e.printStackTrace();
}
}
}
}
}, 0, 10000);
return;
} else {
event.getTextChannel().sendMessage("timeRole is Active!").queue();
help(event);
return;
}
} else if (args[1].equals("pause")) {
if (isRunning) {
timer.cancel();
event.getTextChannel().sendMessage("Paused timeRole").queue();
;
isRunning = false;
} else {
event.getTextChannel().sendMessage("timeRole is Paused!").queue();
help(event);
return;
}
return;
} else {
event.getTextChannel().sendMessage("Please give one **Argument**").queue();
help(event);
return;
}
}
}
}
Code for the "Server" Class:
package Discord.Commands.TimeRank;
import java.util.ArrayList;
import net.dv8tion.jda.api.OnlineStatus;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
public class Server {
public ArrayList<Client> clients = new ArrayList<Client>();
public ArrayList<Client> onlineClients = new ArrayList<Client>();
public Guild guild;
private Server(Guild guild) {
this.guild = guild;
}
public static Server get(Guild guild) {
Server server = new Server(guild);
server.clients = server.getMembersAsClients();
server.onlineClients = server.getOnlineMembersAsClients();
return server;
}
public ArrayList<Client> getMembersAsClients() {
ArrayList<Client> clients = new ArrayList<Client>();
System.out.println(guild.getMembers().size());
for (Member member : guild.getMembers()) {
if (!member.getUser().isBot()) {
clients.add(new Client(member));
}
}
return clients;
}
public ArrayList<Client> getOnlineMembersAsClients() {
ArrayList<Client> onlineClients = new ArrayList<Client>();
for (Client client : clients) {
if (!client.member.getUser().isBot()) {
if (client.member.getOnlineStatus() == OnlineStatus.ONLINE) {
onlineClients.add(client);
}
}
}
return onlineClients;
}
}
and Time Class:
package Discord.Commands.TimeRank;
public class Time {
public int Days, Hours, Minutes, Seconds;
public Time() {
}
public String get() {
return Days + "D " + Hours + "H " + Minutes + "min " + Seconds + "sec ";
}
public void plus(int plus) {
Seconds += plus;
if (Seconds >= 60) {
Seconds = 0;
Minutes++;
if (Minutes >= 60) {
Minutes = 0;
Hours++;
if (Hours >= 24) {
Hours = 0;
Days++;
return;
}
}
}
}
public void setTime(String Time) {
String[] Time_ = Time.split(" ");
int Days = Integer.parseInt(Time_[0].split("D")[0]);
int Hours = Integer.parseInt(Time_[1].split("H")[0]);
int Minutes = Integer.parseInt(Time_[2].split("min")[0]);
int Seconds = Integer.parseInt(Time_[3].split("sec")[0]);
this.Days = Days;
this.Hours = Hours;
this.Minutes = Minutes;
this.Seconds = Seconds;
}
}
And the Error:
[DefaultShardManager] INFO RateLimiter - Waiting for 1 bucket(s) to finish. Average queue size of 2 requests
Exception in thread "Timer-0" java.util.concurrent.RejectedExecutionException: The Requester has been stopped! No new requests can be requested!
at net.dv8tion.jda.internal.requests.Requester.request(Requester.java:107)
at net.dv8tion.jda.internal.requests.RestActionImpl.queue(RestActionImpl.java:189)
at net.dv8tion.jda.internal.managers.ManagerBase.queue(ManagerBase.java:121)
at net.dv8tion.jda.api.requests.RestAction.queue(RestAction.java:411)
at net.dv8tion.jda.api.requests.RestAction.queue(RestAction.java:377)
at Discord.Commands.TimeRank.startTimeRole$1.run(startTimeRole.java:67)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
Sorry for that much Code but I just thoght that you could need it to know what, what is.
If you have some questions Just ask them. :D
You are being rate limited. Different requests to the api have different limits on how often you are allowed to perform them. When spamming a request you can easily hit such a limit.
Switching the bot works because every new bot starts at zero until you hit the limit again.
My advice is to decrease the number of requests. Trying to circumvent the limit it therefore abusing the api is against TOS.
Related
class ImageList implements ListModel<Image> {
private int selection;
private Image[] images;
private EventDispatcher listeners = new EventDispatcher();
public ImageList() {
this.images = new EncodedImage[imageURLs.length];
}
public Image getItemAt(final int index) {
if (images[index] == null) {
images[index] = placeholderForTable;
Util.downloadUrlToStorageInBackground(imageURLs[index], "list" + index, (e) -> {
try {
images[index] = EncodedImage.create(Storage.getInstance().createInputStream("list" + index));
listeners.fireDataChangeEvent(index, DataChangedListener.CHANGED);
} catch (IOException err) {
err.printStackTrace();
}
});
}
return images[index];
}
public int getSize() {
return imageURLs.length;
}
public int getSelectedIndex() {
return selection;
}
public void setSelectedIndex(int index) {
selection = index;
}
public void addDataChangedListener(DataChangedListener l) {
listeners.addListener(l);
}
public void removeDataChangedListener(DataChangedListener l) {
listeners.removeListener(l);
}
public void addSelectionListener(SelectionListener l) {
}
public void removeSelectionListener(SelectionListener l) {
}
public void addItem(Image item) {
}
public void removeItem(int index) {
}
}
protected void postMenuForm(Form f) {
BusinessForumImagesConnection bfic = new BusinessForumImagesConnection();
bfic.businessForumImagesConnectionMethod(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
if (bfic.response != null) {
for (int i = 0; i < imgLoop; i++) {
HashMap hm = (HashMap) bfic.response.get(i);
String imgUrl = (String) hm.get("imgUrl");
imageURLs[i] = imgUrl;
}
}
}
});
if (imageURLs != null) {
ImageList imodel = new ImageList();
ImageViewer iv = new ImageViewer(imodel.getItemAt(0));
iv.setImageList(imodel);
Container adsContainer = BoxLayout.encloseY(adsLabel, iv);
slideIndex = 0;
Runnable r = new Runnable() {
public void run() {
if (slideIndex < imodel.getSize()) {
nextImage = (Image) imodel.getItemAt(slideIndex);
if (nextImage != null) {
iv.setImage(nextImage);
}
slideIndex++;
} else {
slideIndex = 0;
}
}
};
if (uITimer == null) {
uITimer = new UITimer(r);
}
if (uITimer != null) {
uITimer.schedule(5000, true, f); //5 seconds
}
f.add(BorderLayout.SOUTH, adsContainer);
adsContainer.setLeadComponent(adsLabel);
adsLabel.addActionListener((e) -> {
showForm("BusinessForum", null);
});
}
}
I had used URLImage.createToStorage before but imageViewer didnt work properly so I have used ImageList model. But everytime the form is opened, it jst redownloads the imgs and overrides them in storage, that makes the app slower. How can I make sure if the image is already downloaded, it doesnt download it again and jst shows them in imgViewer? thankyou
The download method will always download regardless...
You need to check if the Storage file exists and if so load that.
See the WebServices/Dogs demo in the new kitchen sink: http://www.codenameone.com/blog/kitchensink-ii.html
I want to get all video files from the internal memory of the device.
I have tried the following ways without getting a result
File file[] = Environment.getExternalStorageDirectory().listFiles();
File file= Environment.getDataDirectory();
File file[] = Environment.getRootDirectory().listFiles();
File file = Environment.getExternalStoragePublicDirectory();
I got the solution for this..Please look into below code
import android.os.Environment;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class ExternalStorage {
public static final String SD_CARD = "sdCard";
public static final String EXTERNAL_SD_CARD = "externalSdCard";
/**
* #return True if the external storage is available. False otherwise.
*/
public static boolean isAvailable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
public static String getSdCardPath() {
return Environment.getExternalStorageDirectory().getPath() + "/";
}
/**
* #return True if the external storage is writable. False otherwise.
*/
public static boolean isWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
/**
* #return A map of all storage locations available
*/
public static Map<String, File> getAllStorageLocations() {
Map<String, File> map = new HashMap<String, File>(10);
List<String> mMounts = new ArrayList<String>(10);
List<String> mVold = new ArrayList<String>(10);
mMounts.add("/mnt/sdcard");
mVold.add("/mnt/sdcard");
try {
File mountFile = new File("/proc/mounts");
if(mountFile.exists()){
Scanner scanner = new Scanner(mountFile);
while (scanner.hasNext()) {
String line = scanner.nextLine();
if (line.startsWith("/dev/block/vold/")) {
String[] lineElements = line.split(" ");
String element = lineElements[1];
// don't add the default mount path
// it's already in the list.
if (!element.equals("/mnt/sdcard"))
mMounts.add(element);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
try {
File voldFile = new File("/system/etc/vold.fstab");
if(voldFile.exists()){
Scanner scanner = new Scanner(voldFile);
while (scanner.hasNext()) {
String line = scanner.nextLine();
if (line.startsWith("dev_mount")) {
String[] lineElements = line.split(" ");
String element = lineElements[2];
if (element.contains(":"))
element = element.substring(0, element.indexOf(":"));
if (!element.equals("/mnt/sdcard"))
mVold.add(element);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
for (int i = 0; i < mMounts.size(); i++) {
String mount = mMounts.get(i);
if (!mVold.contains(mount))
mMounts.remove(i--);
}
mVold.clear();
List<String> mountHash = new ArrayList<String>(10);
for(String mount : mMounts){
File root = new File(mount);
if (root.exists() && root.isDirectory() && root.canWrite()) {
File[] list = root.listFiles();
String hash = "[";
if(list!=null){
for(File f : list){
hash += f.getName().hashCode()+":"+f.length()+", ";
}
}
hash += "]";
if(!mountHash.contains(hash)){
String key = SD_CARD + "_" + map.size();
if (map.size() == 0) {
key = SD_CARD;
} else if (map.size() == 1) {
key = EXTERNAL_SD_CARD;
}
mountHash.add(hash);
map.put(key, root);
}
}
}
mMounts.clear();
if(map.isEmpty()){
map.put(SD_CARD, Environment.getExternalStorageDirectory());
}
return map;
}
}
In our current framework we are taking screenshots onTestFailure. And now we have implemented 'IRetryAnalyzer' using which are re-running the failed tests.
Here when the test fails for the first time, it is taking the screen shot and keeping it in a folder which indicates 'Failed Test', which may get passed in the next attempt.
When we submit final Automation report, we need to submit screenshots also. In Screenshots folder, currently passed (after re-running) test images are also attached.
Can we take a screenshot only when the Test has failed Even After Re-running by ignoring the previous test fails.
Please suggest if there is any other alternative.
Below is the code for Retry
#Override
public boolean retry(ITestResult result) {
boolean iFlag=false;
String resultString = result.getThrowable().toString();
//Checking for specific reason of failure
if (resultString.contains("NoSuchElementException") || resultString.contains("TimeoutException") ) {
if (retryCount < maxRetryCount) {
System.out.println("Retrying " + result.getName()+ " test for the "+ (retryCount + 1) + " time(s).");
retryCount++;
iFlag=true;
}
} else {
//making retryCount and maxRetryCount equal
retryCount=0;
maxRetryCount=0;
iFlag=false;
}
return iFlag;
}
Below is the code for On Test failure
private static int retryCount=0;
private static int maxRetryCount=1;
#Override
public void onTestFailure(ITestResult result) {
System.out.println("***** Error "+result.getName()+" test has failed *****");
String methodName=result.getName().toString().trim();
//takeScreenShot(methodName);
driver=TestBase.getDriver();
if( driver != null && retryCount == maxRetryCount) {
takeScreenShot(driver, methodName);
}
}
Try to put both onTestFailure/AfterMethod and retry methods in same class like Retry or any suitable name. And there you can define your methods as:
private static int retryCount = 0;
private static int maxRetryCount = 2;
#AfterMethod
public void tearDown(ITestResult result) throws IOException {
String methodname = result.getName();
WebDriver augmentedDriver = new Augmenter().augment(driver);
try {
if (driver != null
&& ((RemoteWebDriver) driver).getSessionId() != null
&& !result.isSuccess() && retryCount == maxRetryCount) {
File scrFile = ((TakesScreenshot) augmentedDriver)
.getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(("./test-output/archive/"
+ "screenshots/" + methodname + "_" + System.currentTimeMillis() + ".png")));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
driver.quit();
}
}
#Override
public boolean retry(ITestResult result) {
boolean res = false;
try {
if (result.getThrowable().toString()
.contains("NoSuchElementException")) {
if (retryCount < maxRetryCount) {
retryCount++;
res = true;
} else if (retryCount == maxRetryCount) {
retryCount = 0;
res = false;
}
} else {
retryCount = 0;
}
return res;
} catch (Exception e) {
return false;
}
}
I need to get the IMSI (International
Mobile Subsriber Identity) stored in the SIM card using codename1. Also in the case of dual or tri SIM phones, i need to get the IMSI for each SIM. Please, How do i get it?
Display.getMsisdn() will work for some devices but most don't allow accessing that information. For more information you can just use a native interface if you can access it that way.
Another way to get IMSI for dual Sim device:
Try this .. its working for me. Idea is to call service for iphonesubinfo function#3. you will get output as parcel value thats why I use getNumberFromParcel to extract number.
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Created by Apipas on 6/4/15.
*/
public class SimUtil {
public static String getIMSI_1() {
String imsiParcel = runCommand("service call iphonesubinfo 3");
String imsi = getNumberFromParcel(imsiParcel);
Log.d("apipas", "IMSI_1:" + imsi);
return imsi;
}
public static String getIMSI_2() {
String imsiParcel = runCommand("service call iphonesubinfo2 3");
String imsi = getNumberFromParcel(imsiParcel);
Log.d("apipas", "IMSI_2:" + imsi);
return imsi;
}
public static String runCommand(String src) {
try {
Process process = Runtime.getRuntime().exec(src);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[2048];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
// Waits for the command to finish.
process.waitFor();
return output.toString();
} catch (IOException e) {
Log.e("apipas", "IOException:" + e.getMessage());
return null;
} catch (InterruptedException e) {
Log.e("apipas", "InterruptedException:" + e.getMessage());
return null;
}
}
public static String getNumberFromParcel(String str) {
String res = "";
if (str != null && str.length() > 0) {
String lines[] = str.split("\n");
for (String line : lines) {
if (line == null || line.length() == 0)
continue;
String content[] = line.split("'");
if (content.length > 1) {
res += content[1].replace(".", "");
}
}
} else return "NA";
return res;
}
}
Then call these static methods like:
String imsi1 = SimUtil.getIMSI_1();
String imsi2 = SimUtil.getIMSI_2();
You'd need to set this permission:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
In GAE, I've got a table full of "one offs" -- things like "last-used sequence number" and the like that don't really fall into other tables. It's a simple String-key with String-value pair.
I've got some code to grab a named integer and increment it, like so:
#PersistenceCapable(detachable="true")
public class OneOff
{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private String dataKey;
#Persistent
private String value;
public OneOff(String kk, String vv)
{
this.dataKey = kk;
this.value = vv;
}
public static OneOff persistOneOff(String kk, String vv)
{
OneOff oneoff= new OneOff(kk, vv);
PersistenceManager pm = PMF.get().getPersistenceManager();
try
{
pm.makePersistent(oneoff);
}
finally
{
pm.close();
}
return oneoff;
}
// snip...
#SuppressWarnings("unchecked")
synchronized
public static int getIntValueForKeyAndIncrement(String kk, int deFltValue)
{
int result = 0;
OneOff oneOff = null;
PersistenceManager pm = PMF.get().getPersistenceManager();
Query query = pm.newQuery(OneOff.class);
query.setFilter("dataKey == kkParam");
query.declareParameters("String kkParam");
List<OneOff> oneOffs = (List<OneOff>) query.execute(kk);
int count = oneOffs.size();
if (count == 1)
{
oneOff = oneOffs.get(0);
result = Integer.parseInt(oneOff.value);
}
else if (count == 0)
{
oneOff = new OneOff(kk, "default");
result = deFltValue;
}
else
{
// Log WTF error.
}
// update object in DB.
oneOff.value = "" + (result+1);
try
{
pm.makePersistent(oneOff);
}
finally
{
pm.close();
}
return result;
}
// etc...
However, when I make these calls:
int val1 = OneOff.getIntValueForKeyAndIncrement("someKey", 100);
int val2 = OneOff.getIntValueForKeyAndIncrement("someKey", 100);
int val3 = OneOff.getIntValueForKeyAndIncrement("someKey", 100);
Sometimes I get the desired increment and sometimes I get the same value. It appears that my DB access is running asynchronously, when I'd like to lock the DB for this particular transaction.
I thought that
synchronized
public static
was supposed to do that for me, but apparently not (probably due to multiple instances running!)
At any rate -- how do I do the thing that I want? (I want to lock my DB while I get & update this value, to make the whole thing concurrency-safe.)
Thanks!
== EDIT ==
I have accepted Robert's as the correct answer, since transactions were, indeed, what I wanted. However, for completeness, I have added my updated code below. I think it's correct, although I'm not sure about the if(oneOff==null) clause (the try-catch bit.)
public static int getIntValueForKeyAndIncrement(String kk, int defltValue)
{
int result = 0;
Entity oneOff = null;
int retries = 3;
// Using Datastore Transactions
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
while (true)
{
com.google.appengine.api.datastore.Transaction txn = datastore.beginTransaction();
try
{
Key oneOffKey = KeyFactory.createKey("OneOff", kk);
oneOff = datastore.get (oneOffKey);
result = Integer.parseInt((String) oneOff.getProperty("value"));
oneOff.setProperty("value", "" + (result+1));
datastore.put(oneOff);
txn.commit();
break;
}
catch (EntityNotFoundException ex)
{
result = defltValue;
}
catch (ConcurrentModificationException ex)
{
if (--retries < 0)
{
throw ex;
}
}
if (oneOff == null)
{
try
{
Key oneOffKey = KeyFactory.createKey("OneOff", kk);
oneOff = new Entity(oneOffKey);
oneOff.setProperty("value", "" + (defltValue+1));
datastore.put(txn, oneOff);
datastore.put(oneOff);
txn.commit();
break;
}
finally
{
if (txn.isActive())
{
txn.rollback();
}
}
}
else
{
if (txn.isActive())
{
txn.rollback();
}
}
}
return result;
}
You should be updating your values inside a transaction. App Engine's transactions will prevent two updates from overwriting each other as long as your read and write are within a single transaction. Be sure to pay attention to the discussion about entity groups.