I'm building my first telegram bot. It send one message every 5 seconds to the user.
While it sends it to one user it cannot receive update from other chat.
public void foo(msg, Update update){
msg.setChatId(update.getMessage().getChatId());
for (int i = 1; i < links.size(); i++){
msg.setText(links.get(i));
execute(msg);
}
Thread.sleep(wait * 1000);
}
How can I use Thread? I've tried creating multiple thread here
public static void bot(){
ApiContextInitializer.init();
TelegramBotsApi telegramBotsApi = new TelegramBotsApi();
try {
telegramBotsApi.registerBot(new myBot());
} catch (TelegramApiException e) {
e.printStackTrace();
}
But he tries to create multiple bots and fails. Same if this is the runnable function:
How can I do it? I'm Stuck. I cannot create this function in different thread
public void onUpdateReceived(Update update) {
leggi(new SendMessage(), update.getMessage().getText(), update);
//.setChatId(update.getMessage().getChatId())
public void leggi(SendMessage msg, String command, Update update){
if(command.equals("test") {
foo( msg, update);
}
Here the full code... https://github.com/siamoInPochi/Ilsottomarinobot/tree/prova/src/main/java/Ilsottomarinobot
If you spawn a thread for every bot user who wants to receive messages, you will quickly be out of computer's resources in case of high number of users. So I think threads is not a good idea for your task.
In my mind more natural approach is the following:
Find a library with an HTTP server.
Switch from GetUpdates to webhooks.
Schedule send-message-to-user-every-5-seconds tasks to server's event loop.
Send messages every 5 seconds asynchronously.
You can make it with this library https://github.com/pengrad/java-telegram-bot-api
<dependency>
<groupId>com.github.pengrad</groupId>
<artifactId>java-telegram-bot-api</artifactId>
<version>4.2.0</version>
</dependency>
Subscribe to new updates via bot.setUpdatesListener
Send messages via bot.execute(new SendMessage(chatId, link), callback)
Full working example:
static String[] links = {"1", "2", "3"};
static Callback emptyCallback = new Callback() {
#Override
public void onResponse(BaseRequest request, BaseResponse response) {
}
#Override
public void onFailure(BaseRequest request, IOException e) {
e.printStackTrace();
}
};
static void foo(TelegramBot bot, Update update) {
Message message = update.message();
if (message == null) return;
Long chatId = message.chat().id();
for (String link : links) {
bot.execute(new SendMessage(chatId, link), emptyCallback);
}
}
public static void main(String[] args) {
TelegramBot bot = new TelegramBot(TOKEN);
bot.setUpdatesListener(updates -> {
for (Update update : updates) {
foo(bot, update);
}
return UpdatesListener.CONFIRMED_UPDATES_ALL;
});
}
Related
I'm trying to build a system in which I can connect some devices to a server over the internet.
I want to stream some data over CoAP (10-30FPS), frame size = 3KB.
Firstly, I used Aiocoap, it sends up to 100FPS but uses too much CPU,
requests are NON, got low lose rate in Aiocoap,
while Eclipse/Californium could not send more than 3FPS,
when i use higher FPS, either I receive only the first block of each message or receiving nothing, also not ordered most of the times.
I was wondering if this is the real performance of Californium or am I using it in a wrong way?
I will share some code:
server.java
static class CoapObserverServer extends CoapResource {
int i = -1;
public CoapObserverServer() {
super("alarm");
setObservable(true); // enable observing
setObserveType(Type.NON); // configure the notification type to CONs
getAttributes().setObservable(); // mark observable in the Link-Format
System.out.println(this);
// schedule a periodic update task, otherwise let events call changed()
//new Timer().schedule(new UpdateTask(), 0, 1000/2);
}
private class UpdateTask extends TimerTask {
#Override
public void run() {
changed(); // notify all observers
}
}
#Override
public void handleGET(CoapExchange exchange) {
// the Max-Age value should match the update interval
exchange.setMaxAge(1);
//++i;
int leng = 2000;
String s = "" + i + "-" + fillString('X', leng - 1 - Integer.toString(i).len>
exchange.respond(s);
}
public static String fillString(char fillChar, int count){
// creates a string of 'x' repeating characters
char[] chars = new char[count];
while (count>0) chars[--count] = fillChar;
return new String(chars);
}
#Override
public void handleDELETE(CoapExchange exchange) {
delete(); // will also call clearAndNotifyObserveRelations(ResponseCode.NOT_>
exchange.respond(ResponseCode.DELETED);
}
#Override
public void handlePUT(CoapExchange exchange) {
exchange.accept();
int format = exchange.getRequestOptions().getContentFormat();
if (format == MediaTypeRegistry.TEXT_PLAIN) {
// ...
String plain = exchange.getRequestText();
try{
i = Integer.valueOf(plain);
} catch(NumberFormatException ex){
System.out.println("error converting string"+ plain);
}
exchange.respond(ResponseCode.CHANGED);
changed(); // notify all observers
}
}
Observer.java
private static final File CONFIG_FILE = new File("Californium3.properties");
private static final String CONFIG_HEADER = "Californium CoAP Properties file for client";
private static final int DEFAULT_MAX_RESOURCE_SIZE = 2 * 1024 * 1024; // 2 MB
private static final int DEFAULT_BLOCK_SIZE = 512;
static {
CoapConfig.register();
UdpConfig.register();
}
private static DefinitionsProvider DEFAULTS = new DefinitionsProvider() {
#Override
public void applyDefinitions(Configuration config) {
config.set(CoapConfig.MAX_RESOURCE_BODY_SIZE, DEFAULT_MAX_RESOURCE_SIZE);
config.set(CoapConfig.MAX_MESSAGE_SIZE, DEFAULT_BLOCK_SIZE);
config.set(CoapConfig.PREFERRED_BLOCK_SIZE, DEFAULT_BLOCK_SIZE);
}
};
private static class AsynchListener implements CoapHandler {
#Override
public void onLoad(CoapResponse response) {
System.out.println( response.getResponseText() );
}
#Override
public void onError() {
System.err.println("Error");
}
}
/*
* Application entry point.
*/
public static void main(String args[]) {
Configuration config = Configuration.createWithFile(CONFIG_FILE, CONFIG_HEADER, DEFAULTS);
Configuration.setStandard(config);
URI uri = null; // URI parameter of the request
if (args.length > 0) {
// input URI from command line arguments
try {
uri = new URI(args[0]);
} catch (URISyntaxException e) {
System.err.println("Invalid URI: " + e.getMessage());
System.exit(-1);
}
CoapClient client = new CoapClient(uri);
client.useNONs();
// observe
AsynchListener asynchListener = new AsynchListener();
CoapObserveRelation observation = client.observe(asynchListener);
// User presses ENTER to exit
System.out.println("Press ENTER to exit...");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try { br.readLine(); } catch (IOException e) { }
System.out.println("Exiting...");
observation.proactiveCancel();
}
So i'm controlling the FPS by sending PUT requests with a server that has a counter 0-50.
Not sure, what your doing.
That seems to be wired and not related to RFC7252 nor RFC7641.
CoAP is designed for REST, I don't see any benefit in using it for video streaming.
Using Eclipse/Californium on a Intel n6005 with 16GB RAM, the CoAP/DTLS server runs on about 60000 requests/second. The benchmark uses 2000 clients in parallel.
See also Eclipse/Californium - Benchmarks j5005
Using only one client with CON requests, the performance is mainly limited by the RTT. 30 requests/second should work, if that RTT is accordingly small.
Using NON requests doesn't really help. CoAP RFC7252 defines two layers, a messaging layer and an application layer. NON affects only the messaging layer, but a NON request will wait for it's response, if NSTART-1 should be used.
If your RTT is the issue, you may try to escape that either using requests with "No Server Response" (RFC7967) or multiple NON responses (RFC7641). The first is not intended for fast requests, the second is more a work-around of the initial statement, that CoAP is REST not video-streaming.
So, what is your RTT?
I have a Java program that reads text files and processes them sequentially and on completion of each file a mail is triggered in a separate thread (using runnable). I have configured this program as a cron job in crontab to run every 15 mins.
The cron does not get triggered if the child thread of the last job run takes more than 20 minutes to send the email. How can I have the job triggered every 15 minutes, even if the last child thread is still executing?
Below is the code used::
EpdFeedLoader.java
public class EpdFeedLoader {
public static void main(String[] args) throws Exception {
startProcess(feedFile);
}
public static void startProcess(BatchFeedFile feedFile) {
EpdBatchLoader epdBatchLoader = new EpdBatchLoader(feedFile);
epdBatchLoader.execute();
}
}
EpdBatchLoader.java
public class EpdBatchLoader {
private static void sendDelayedFeedEmail(){
SendDelayedFeedJobStatusMail delayedFeedEmail = new SendDelayedFeedJobStatusMail();
delayedFeedEmail.setParameters(//parameters for my email method);
Thread delayedFeedThread = new Thread(delayedFeedEmail);
delayedFeedThread.start();
}
}
SendDelayedFeedJobStatusMail.java
public class SendDelayedFeedJobStatusMail implements Runnable {
private MailRequestDTO mailRequestDTO;
public void setParameters(MailRequestDTO mailRequestDTO){
this.mailRequestDTO = mailRequestDTO;
}
public void sendMail() {
boolean isSend = false;
message.setSubject(subject);
message.setSentDate(Utils.getDateInTimeZone(mailRequestDTO.getCountryCode(),new Date()));
message.setContent(mailRequestDTO.getMessageContent(), "text/html");
message.addHeader("Content-Transfer-Encoding", "7bit");
attachInlineImages(message, mailRequestDTO.getInlineImageMap());
ConfigUtils.logger.info("Ready to Send Delayed Feed Receipt Email for Process Code : " + mailRequestDTO.getProcessCode().toString());
Transport.send(message);
isSend = true;
ConfigUtils.logger.info("Delayed Feed Receipt Email Sent Successfully for Process Code : " + mailRequestDTO.getProcessCode().toString());
}
#Override
public void run(){
this.sendMail();
}
}
I want to implement a very simple Java Telegram Client, which is capable of sending and receiving messages and store the sessions across multiple starts. I already managed to authenticate and receive messages
api = new TelegramApi(apiState, new AppInfo(API_ID, "console", "1", "1", "en"), new ApiCallback() {
#Override
public void onAuthCancelled(TelegramApi api) {
Log.d(TAG, "-----------------CANCELLED----------------");
Log.d(TAG, api.getApiContext().toString());
}
#Override
public void onUpdatesInvalidated(TelegramApi api) {
Log.d(TAG, "-----------------INVALIDATED----------------");
Log.d(TAG, api.getApiContext().toString());
}
#Override
public void onUpdate(TLAbsUpdates tlAbsUpdates) {
Log.d(TAG, "-----------------UPDATE----------------");
Log.d(TAG, tlAbsUpdates.toString());
if (tlAbsUpdates instanceof TLUpdateShortMessage) {
Log.d(TAG, "-----------------UPDATE CHAT MESSAGE----------------");
int senderId = ((TLUpdateShortMessage) tlAbsUpdates).getUserId();
Log.d(TAG, "Message from " + senderId);
String message = ((TLUpdateShortMessage) tlAbsUpdates).getMessage();
Log.d(TAG, message);
activity.appendMessage(TAG, message);
}
}
});
api.switchToDc(2);
TLConfig config = null;
try {
config = api.doRpcCallNonAuth(new TLRequestHelpGetConfig());
} catch (TimeoutException | IOException e) {
e.printStackTrace();
}
apiState.updateSettings(config);
However, I struggle to send messages to another user. For the beginning, it would be enough if I could send a message back to the user, who sent me a message before (by retrieving the senderId, as you can see in the onUpdate method before). However, if someone could also help me with retrieving the ids of my saved contacts, it would be perfect.
Furthermore, I want to store the sessions accross multiple startups, since I get a FLOOD_WAIT error (420), if I test my code to often.
For this I used https://github.com/rubenlagus/TelegramApi/blob/51713e9b6eb9e0ae0d4bbbe3d4deffff9b7f01e4/src/main/java/org/telegram/bot/kernel/engine/MemoryApiState.java and its used classes (e.g. TLPersistence), which stores and loads the ApiState. However, apparently it does not store the signin status, since I always have to authenticate my number every time I update the code.
By the way, I am using Api layer 66 (https://github.com/rubenlagus/TelegramApi/releases).
UPDATE 1:
Problems with sending messages solved myself:
private void sendMessageToUser(int userId, String message) {
TLInputPeerUser peer = new TLInputPeerUser();
peer.setUserId(userId);
TLRequestMessagesSendMessage messageRequest = new TLRequestMessagesSendMessage();
messageRequest.setFlags(0);
messageRequest.setPeer(peer);
messageRequest.setRandomId(new SecureRandom().nextLong());
messageRequest.setMessage(message);
api.doRpcCallNonAuth(messageRequest, 1500, new RpcCallback<TLAbsUpdates>() {
#Override
public void onResult(TLAbsUpdates tlAbsUpdates) {
Log.d(TAG, "-----------------------MESSAGE SENT-----------------------");
}
#Override
public void onError(int i, String s) {
Log.d(TAG, "-----------------------MESSAGE SENT ERROR-----------------------");
Log.d(TAG, String.valueOf(i));
if(s != null) {
Log.d(TAG, s);
}
}
});
}
However, now I am stuck at finding the userIds of my contacts.
After first update this is left:
Saving the session state (and signin state)
Find userIds of contacts
Update 2:
I managed to fetch the users, with which there are already dialogs. This is enough for my use case, however, loading all contacts would be perfect. This is how to load users from existing dialogs:
private int getUserId(String phone) throws InterruptedException {
TLRequestMessagesGetDialogs dialogs = new TLRequestMessagesGetDialogs();
dialogs.setOffsetId(0);
dialogs.setLimit(20);
dialogs.setOffsetPeer(new TLInputPeerUser());
CountDownLatch latch = new CountDownLatch(1);
api.doRpcCallNonAuth(dialogs, 1500, new RpcCallback<TLAbsDialogs>() {
#Override
public void onResult(TLAbsDialogs tlAbsDialogs) {
Log.d(TAG, "----------------------getUsers--------------------");
for(TLAbsUser absUser : ((TLDialogs) tlAbsDialogs).getUsers()) {
users.add((TLUser) absUser);
}
latch.countDown();
}
#Override
public void onError(int i, String s) {
Log.d(TAG, "----------------------getUsers ERROR--------------------");
latch.countDown();
}
});
latch.await();
for(TLUser user : users) {
if(user.getPhone().equals(phone)) {
return user.getId();
}
}
return 0;
}
After second update this is left:
Saving the session state (and signin state)
Get user ids from contacts instead of dialogs
i've done a rest web service that gives me some contact information like numbers, age ... i get all this information in this function
public static void getRest(String search) {
if(search.equals("")){
json="http://localhost:8080/com.vogella.jersey.first/rest/jsonServices/print/";
} else {
json="http://localhost:8080/com.vogella.jersey.first/rest/jsonServices/print/"+search;
}
ConnectionRequest req = new ConnectionRequest() {
#Override
protected void postResponse() {
}
#Override
protected void readResponse(InputStream input) throws IOException {
JSONParser p = new JSONParser();
Map<String, Object> h = p.parseJSON(new InputStreamReader(input));
ArrayList object=new ArrayList();
for (Entry<String, Object> entry : h.entrySet()) {
object = (ArrayList) entry.getValue();
int i=object.size();
}
for(int i=0; i<object.size();i++){
LinkedHashMap s= (LinkedHashMap) object.get(i);
Risultati.add(s);
}
}
};
req.setUrl(json);
req.setPost(false);
req.addRequestHeader("Accept", "application/json");
InfiniteProgress prog = new InfiniteProgress();
Dialog dlg = prog.showInifiniteBlocking();
req.setDisposeOnCompletion(dlg);
NetworkManager.getInstance().addToQueue(req);
Risultati is an attribute of the class: ArrayList<LinkedHashMap> Risultati;
the problem is that when i call the function getRest("") in this way:
getRest("");
Label contatto=null;
for(int j=0;j<Risultati.size();j++){
LinkedHashMap s=Risultati.get(j);
String nome=(String) s.get("firstName");
String cognome=(String) s.get("lastName");
String numero =(String) s.get("numero");
contatto=new Label(nome+" "+cognome+" "+numero);
}
hi.addComponent(contatto);
it turns that Risultati is null, if i comment the for cycle i notice that the inner function readResponse is executed after...i don't know what i'm doing wrong
I think the point is that you're calling NetworkManager.getInstance().addToQueue(req). According to it's documentation, it will add a connection request (the one you've just created) to a queue. After the connection request is added to the queue, it returns, meaning the request may or may not have been executed by that time.
You have to options to deal with this. In my opinion, the best way would be to update the user interface after the request has completed, as described in the "File System, Storage, Network & Parsing" chapter of the CodeOne manual:
req.addResponseListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
NetworkEvent e = (NetworkEvent)ev;
// ... process the response
}
});
Alternatively, you could replace the call to addToQueue(req) with addToQueueAndWait(req). The latter method waits until the request is processed in the queue. The downside of the latter approach is that your user interface may freeze while the request is being processed, because the UI thread is blocked on the network I/O.
i used the java telegram api to communicate with telegram core api in windows intellij idea
https://github.com/ex3ndr/telegram-api
But the app is facing Timeout error in line TLConfig config = api.doRpcCall(new TLRequestHelpGetConfig());Full source code:
AppInfo appinfo=new AppInfo(45687, "Myapp", "154", "587","en");
TLRequestAuthCheckPhone checkRequest = new TLRequestAuthCheckPhone("96521452365");
MyApiStorage state=new MyApiStorage();
TelegramApi api = new TelegramApi(state, appinfo, new ApiCallback()
{
public void onApiDies(TelegramApi api) {
// When auth key or user authorization dies
}
#Override
public void onUpdatesInvalidated(TelegramApi api) {
System.out.print("############################### onUpdatesInvalidated");
// When api engine expects that update sequence might be broken
}
#Override
public void onAuthCancelled(TelegramApi ta) {
System.out.print("############################### onAuthCancelled");
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void onUpdate(TLAbsUpdates updates) {
System.out.print("############################### onUpdate");
System.out.println("user Id ::::"+((TLUpdateShortMessage) updates).getFromId());
}
});
api.switchToDc(1);
TLConfig config = api.doRpcCall(new TLRequestHelpGetConfig());
System.out.print("############################### config" + config.getTestMode());
state.updateSettings(config);
api.doRpcCall(checkRequest, new RpcCallbackEx<TLCheckedPhone>() {
public void onConfirmed() {
System.out.print("############################### onConfirmed");
}
public void onResult(TLCheckedPhone result) {
boolean invited = result.getPhoneInvited();
boolean registered = result.getPhoneRegistered();
System.out.print("############################### onResult" + registered);
// TODO process response further
}
public void onError(int errorCode, String message) {
System.out.print("############################### onError" + message);
}
});
can someone help me
Your timeout might happen for several reasons:
1. You are using
api.doRpcCall(new TLRequestHelpGetConfig());
In the TelegramApi class this translates into
return this.doRpcCall(method, timeout, 0);
0 there stands for DC. If your DC is different you will timeout
2. There were suggestions in other places to use doRpcCallSide instead and it worked for some and not for others. The reason is it translates into
return this.doRpcCall(method, 15000, this.primaryDc, true);
where true stands authRequired.
3. If you want to do this without authorization then use api.doRpcCallNonAuth