Browse Source

Merge pull request #4 from rubenlagus/dev

Dev
master
Ruben Bermudez 11 years ago
parent
commit
984fc37fc4
  1. 10
      .idea/inspectionProfiles/Project_Default.xml
  2. 1422
      .idea/workspace.xml
  3. 6
      src/main/java/org/telegram/Commands.java
  4. 52
      src/main/java/org/telegram/CustomMessages.java
  5. 58
      src/main/java/org/telegram/SenderHelper.java
  6. 4
      src/main/java/org/telegram/api/Contact.java
  7. 7
      src/main/java/org/telegram/api/Document.java
  8. 6
      src/main/java/org/telegram/api/ForceReplyKeyboard.java
  9. 16
      src/main/java/org/telegram/api/Message.java
  10. 6
      src/main/java/org/telegram/api/Sticker.java
  11. 18
      src/main/java/org/telegram/api/Video.java
  12. 87
      src/main/java/org/telegram/database/CreationStrings.java
  13. 273
      src/main/java/org/telegram/database/DatabaseManager.java
  14. 56
      src/main/java/org/telegram/methods/SendSticker.java
  15. 4
      src/main/java/org/telegram/methods/SendVideo.java
  16. 257
      src/main/java/org/telegram/services/BotLogger.java
  17. 69
      src/main/java/org/telegram/services/CustomTimerTask.java
  18. 63
      src/main/java/org/telegram/services/DirectionsService.java
  19. 188
      src/main/java/org/telegram/services/Emoji.java
  20. 207
      src/main/java/org/telegram/services/LocalisationService.java
  21. 108
      src/main/java/org/telegram/services/TimerExecutor.java
  22. 241
      src/main/java/org/telegram/services/TransifexService.java
  23. 294
      src/main/java/org/telegram/services/WeatherService.java
  24. 40
      src/main/java/org/telegram/structure/WeatherAlert.java
  25. 215
      src/main/java/org/telegram/updateshandlers/DirectionsHandlers.java
  26. 278
      src/main/java/org/telegram/updateshandlers/FilesHandlers.java
  27. 28
      src/main/java/org/telegram/updateshandlers/TransifexHandlers.java
  28. 1
      src/main/java/org/telegram/updateshandlers/UpdatesCallback.java
  29. 1228
      src/main/java/org/telegram/updateshandlers/WeatherHandlers.java
  30. 101
      src/main/java/org/telegram/updatesreceivers/UpdatesThread.java
  31. 21
      src/main/java/org/telegram/updatesreceivers/Webhook.java
  32. 85
      src/main/resources/localisation/strings.properties
  33. 75
      src/main/resources/localisation/strings_es.properties
  34. 75
      src/main/resources/localisation/strings_nl.properties
  35. 75
      src/main/resources/localisation/strings_pt.properties

10
.idea/inspectionProfiles/Project_Default.xml

@ -2,6 +2,8 @@
<profile version="1.0">
<option name="myName" value="Project Default" />
<option name="myLocal" value="true" />
<inspection_tool class="FieldMayBeFinal" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="FieldMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="JSHint" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="JSLint" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
@ -35,5 +37,13 @@
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
<option name="myAdditionalJavadocTags" value="date,brief" />
</inspection_tool>
<inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
<option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
<option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
</inspection_tool>
<inspection_tool class="MethodMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_onlyPrivateOrFinal" value="false" />
<option name="m_ignoreEmptyMethods" value="true" />
</inspection_tool>
</profile>
</component>

1422
.idea/workspace.xml

File diff suppressed because it is too large

6
src/main/java/org/telegram/Commands.java

@ -8,10 +8,6 @@ package org.telegram;
*/
public class Commands {
public static final String commandInitChar = "/";
/// Weather forecast command
public static final String WEATHERCOMMAND = commandInitChar + "weather";
/// Current wether command
public static final String CURRENTWEATHERCOMMAND = commandInitChar + "current";
/// Transifex iOS command
public static final String transifexiOSCommand = commandInitChar + "langios";
/// Transifex android command
@ -40,4 +36,6 @@ public class Commands {
public static final String listCommand = commandInitChar + "list";
/// Start directions command
public static final String startDirectionCommand = commandInitChar + "directions";
/// Set Language command
public static final String setLanguageCommand = commandInitChar + "language";
}

52
src/main/java/org/telegram/CustomMessages.java

@ -1,52 +0,0 @@
package org.telegram;
/**
* @author Ruben Bermudez
* @version 1.0
* @brief Custom messages to be sent to the user
* @date 21 of June of 2015
*/
public class CustomMessages {
public static final String helpWeather = "Curious about the weather?\nJust send me these commands and you'll know a lot better.\n\n" +
"|-- " + Commands.WEATHERCOMMAND + " CITY,COUNTRY : Get a 3-day weather forecast for a city.\n" +
"|-- " + Commands.CURRENTWEATHERCOMMAND + " CITY,COUNTRY : Get the current weather of a city.\n" +
"|-- Send a location to get the forecast for it.";
public static final String helpTransifex = "Tricks with words is the game that I play, give it a shot, I might make your day.\n\n" +
"To get the latest Telegram localization file for a language: \n" +
"|-- " + Commands.transifexiOSCommand + " LANG_CODE : Get the latest iOS language.\n" +
"|-- " + Commands.transifexAndroidCommand + " LANG_CODE : Get the latest android language.\n" +
"|-- " + Commands.transifexWebogram + " LANG_CODE : Get the latest webogram language.\n" +
"|-- " + Commands.transifexiOSCommand + " LANG_CODE : Get the latest iOS language.\n" +
"|-- " + Commands.transifexAndroidCommand + " LANG_CODE : Get the latest android language.\n" +
"|-- " + Commands.transifexWebogram + " LANG_CODE : Get the latest webogram language.\n" +
"|-- " + Commands.transifexTDesktop + " LANG_CODE : Get the latest Tdesktop language.\n" +
"|-- " + Commands.transifexOSX + " LANG_CODE : Get the latest OSX-App language.\n" +
"|-- " + Commands.transifexWP + " LANG_CODE : Get the latest Windows Phone language.\n\n" +
"2. To get an updated localization file for your Android beta-app: \n" +
"|-- " + Commands.transifexAndroidSupportCommand + " LANG_CODE : Get the latest Android-beta language.\n\n";
public static final String helpFiles = "Leaving a file for some others to find? Just dock your boat here and a bay comes to mind.\n\n"+
"Share files through a custom link: \n" +
"|-- " + Commands.startCommand + " FILEID : Get a file by id.\n" +
"|-- " + Commands.uploadCommand + " : Start your file upload.\n" +
"|-- " + Commands.deleteCommand + " : Choose one of your files to delete it.\n" +
"|-- " + Commands.listCommand + " : Show a list of your shared files.\n\n";
public static final String helpDirections = "The road ahead, paved with good intentions, the right path ahead however is what I tend to mention.\n\n" +
"To get directions between two locations: \n" +
"|-- " + Commands.startDirectionCommand + " : Start to get directions\n";
public static final String sendFileToUpload = "Please send me a file you want to share. Make sure you attach it as file, not as an image or video.";
public static final String fileUploaded = "Great, your file has been uploaded. Send this link to anyone you want and they will be able to download the file:\n\n";
public static final String deleteUploadedFile = "Please select the file you want to delete:";
public static final String fileDeleted = "The file was deleted";
public static final String wrongFileId = "Sorry, we can't find a file with that ID. Either a typo was made or it was deleted already.";
public static final String listOfFiles = "This your currently shared files list:";
public static final String noFiles = "You haven't shared any file yet.";
public static final String processFinished = "The current process was cancelled.";
public static final String uploadedFileURL = "https://telegram.me/filesbot?start=";
public static final String chooseFromRecentWeather = "Please choose an option from your recent requests:";
public static final String initDirections = "Please reply with your departing location.";
public static final String sendDestination = "Please reply with your destination.";
public static final String youNeedReplyDirections = "I'm sorry, I can't help you unless you reply to the message I sent you.";
public static final String pleaseSendMeCityWeather = "Send me the city and country you are interested in, use this format: CITY,COUNTRY";
}

58
src/main/java/org/telegram/SenderHelper.java

@ -16,10 +16,8 @@ import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.telegram.api.Message;
import org.telegram.methods.Constants;
import org.telegram.methods.SendDocument;
import org.telegram.methods.SendMessage;
import org.telegram.methods.SetWebhook;
import org.telegram.methods.*;
import org.telegram.services.BotLogger;
import java.io.File;
import java.io.IOException;
@ -34,6 +32,8 @@ import java.util.List;
* @date 20 of June of 2015
*/
public class SenderHelper {
private static volatile BotLogger log = BotLogger.getLogger(SenderHelper.class.getName());
public static Message SendMessage(SendMessage message, String botToken) {
try {
CloseableHttpClient httpclient = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
@ -54,6 +54,8 @@ public class SenderHelper {
nameValuePairs.add(new BasicNameValuePair(SendMessage.REPLYTOMESSAGEID_FIELD, message.getReplayToMessageId().toString()));
}
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
log.debug(httppost.toString());
log.debug(nameValuePairs.toString());
CloseableHttpResponse response = httpclient.execute(httppost);
HttpEntity ht = response.getEntity();
@ -67,7 +69,7 @@ public class SenderHelper {
JSONObject jsonMessage = jsonObject.getJSONObject("result");
return new Message(jsonMessage);
} catch (IOException e) {
e.printStackTrace();
log.error(e);
return null;
}
}
@ -109,7 +111,7 @@ public class SenderHelper {
fileToDelete.delete();
}
} catch (IOException e) {
e.printStackTrace();
log.error(e);
}
}
@ -130,7 +132,49 @@ public class SenderHelper {
String responseContent = EntityUtils.toString(buf, "UTF-8");
} catch (IOException e) {
e.printStackTrace();
log.error(e);
}
}
public static void sendSticker(SendSticker sendSticker, String botToken) {
try {
CloseableHttpClient httpClient = HttpClients.createDefault();
String url = Constants.BASEURL + botToken + "/" + SendSticker.PATH;
HttpPost httppost = new HttpPost(url);
if (sendSticker.isNewSticker()) {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody(SendSticker.CHATID_FIELD, sendSticker.getChatId().toString());
builder.addBinaryBody(SendSticker.STICKER_FIELD, new File(sendSticker.getSticker()), ContentType.APPLICATION_OCTET_STREAM, sendSticker.getStickerName());
if (sendSticker.getReplayMarkup() != null) {
builder.addTextBody(SendSticker.REPLYMARKUP_FIELD, sendSticker.getReplayMarkup().toJson().toString());
}
if (sendSticker.getReplayToMessageId() != null) {
builder.addTextBody(SendSticker.REPLYTOMESSAGEID_FIELD, sendSticker.getReplayToMessageId().toString());
}
HttpEntity multipart = builder.build();
httppost.setEntity(multipart);
} else {
List<NameValuePair> nameValuePairs = new ArrayList<>();
nameValuePairs.add(new BasicNameValuePair(SendSticker.CHATID_FIELD, sendSticker.getChatId().toString()));
nameValuePairs.add(new BasicNameValuePair(SendSticker.STICKER_FIELD, sendSticker.getSticker()));
if (sendSticker.getReplayMarkup() != null) {
nameValuePairs.add(new BasicNameValuePair(SendSticker.REPLYMARKUP_FIELD, sendSticker.getReplayMarkup().toString()));
}
if (sendSticker.getReplayToMessageId() != null) {
nameValuePairs.add(new BasicNameValuePair(SendSticker.REPLYTOMESSAGEID_FIELD, sendSticker.getReplayToMessageId().toString()));
}
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
}
CloseableHttpResponse response = httpClient.execute(httppost);
if (sendSticker.isNewSticker()) {
File fileToDelete = new File(sendSticker.getSticker());
fileToDelete.delete();
}
} catch (IOException e) {
log.error(e);
}
}

4
src/main/java/org/telegram/api/Contact.java

@ -22,7 +22,7 @@ public class Contact {
private String lastName; ///< Optional. Contact's last name
public static final String USERID_FIELD = "user_id";
@JsonProperty(USERID_FIELD)
private String userID; ///< Optional. Contact's user identifier in Telegram
private Integer userID; ///< Optional. Contact's user identifier in Telegram
public Contact() {
super();
@ -33,6 +33,6 @@ public class Contact {
this.phoneNumber = jsonObject.getString(PHONENUMBER_FIELD);
this.firstName = jsonObject.getString(FIRSTNAME_FIELD);
this.lastName = jsonObject.optString(LASTNAME_FIELD, "");
this.userID = jsonObject.optString(USERID_FIELD, "");
this.userID = jsonObject.optInt(USERID_FIELD, 0);
}
}

7
src/main/java/org/telegram/api/Document.java

@ -34,7 +34,12 @@ public class Document {
public Document(JSONObject jsonObject) {
this.fileId = jsonObject.getString(FILEID_FIELD);
this.thumb = new PhotoSize(jsonObject.getJSONObject(THUMB_FIELD));
if (jsonObject.has(THUMB_FIELD)) {
this.thumb = new PhotoSize(jsonObject.getJSONObject(THUMB_FIELD));
}
else {
this.thumb = null;
}
this.fileName = jsonObject.optString(FILENAME_FIELD, "");
this.mimeType = jsonObject.optString(MIMETYPE_FIELD, "");
this.fileSize = jsonObject.optInt(FILESIZE_FIELD, 0);

6
src/main/java/org/telegram/api/ForceReply.java → src/main/java/org/telegram/api/ForceReplyKeyboard.java

@ -12,7 +12,7 @@ import org.json.JSONObject;
* interfaces without having to sacrifice privacy mode.
* @date 22 of June of 2015
*/
public class ForceReply implements ReplyKeyboard {
public class ForceReplyKeyboard implements ReplyKeyboard {
public static final String FORCEREPLY_FIELD = "force_reply";
/**
@ -30,12 +30,12 @@ public class ForceReply implements ReplyKeyboard {
@JsonProperty(SELECTIVE_FIELD)
private Boolean selective;
public ForceReply() {
public ForceReplyKeyboard() {
super();
this.forceReply = true;
}
public ForceReply(JSONObject jsonObject) {
public ForceReplyKeyboard(JSONObject jsonObject) {
super();
this.forceReply = jsonObject.optBoolean(FORCEREPLY_FIELD, true);
this.selective = jsonObject.optBoolean(SELECTIVE_FIELD, false);

16
src/main/java/org/telegram/api/Message.java

@ -71,7 +71,7 @@ public class Message {
private String newChatTitle; ///< Optional. A group title was changed to this value
public static final String NEWCHATPHOTO_FIELD = "new_chat_photo";
@JsonProperty(NEWCHATPHOTO_FIELD)
private String newChatPhoto; ///< Optional. A group photo was change to this value
private List<PhotoSize> newChatPhoto; ///< Optional. A group photo was change to this value
public static final String DELETECHATPHOTO_FIELD = "delete_chat_photo";
@JsonProperty(DELETECHATPHOTO_FIELD)
private Boolean deleteChatPhoto; ///< Optional. Informs that the group photo was deleted
@ -107,7 +107,7 @@ public class Message {
if (jsonObject.has(DOCUMENT_FIELD)) {
this.document = new Document(jsonObject.getJSONObject(DOCUMENT_FIELD));
}
this.photo = new ArrayList<PhotoSize>();
this.photo = new ArrayList<>();
if (jsonObject.has(PHOTO_FIELD)) {
JSONArray photos = jsonObject.getJSONArray(PHOTO_FIELD);
for (int i = 0; i < photos.length(); i++) {
@ -136,7 +136,13 @@ public class Message {
this.replyToMessage = new Message(jsonObject.getJSONObject(REPLYTOMESSAGE_FIELD));
}
this.newChatTitle = jsonObject.optString(NEWCHATTITLE_FIELD, "");
this.newChatPhoto = jsonObject.optString(NEWCHATPHOTO_FIELD, "");
if (jsonObject.has(NEWCHATPHOTO_FIELD)) {
JSONArray photoArray = jsonObject.getJSONArray(NEWCHATPHOTO_FIELD);
this.newChatPhoto = new ArrayList<>();
for (int i = 0; i < photoArray.length(); i++) {
this.newChatPhoto.add(new PhotoSize(photoArray.getJSONObject(i)));
}
}
this.deleteChatPhoto = jsonObject.optBoolean(DELETECHATPHOTO_FIELD, false);
this.groupchatCreated = jsonObject.optBoolean(GROUPCHATCREATED_FIELD, false);
}
@ -293,11 +299,11 @@ public class Message {
this.newChatTitle = newChatTitle;
}
public String getNewChatPhoto() {
public List<PhotoSize> getNewChatPhoto() {
return newChatPhoto;
}
public void setNewChatPhoto(String newChatPhoto) {
public void setNewChatPhoto(List<PhotoSize> newChatPhoto) {
this.newChatPhoto = newChatPhoto;
}

6
src/main/java/org/telegram/api/Sticker.java

@ -36,7 +36,11 @@ public class Sticker {
this.fileId = jsonObject.getString(FILEID_FIELD);
this.width = jsonObject.getInt(WIDTH_FIELD);
this.height = jsonObject.getInt(HEIGHT_FIELD);
this.thumb = new PhotoSize(jsonObject.getJSONObject(THUMB_FIELD));
if (jsonObject.has(THUMB_FIELD)) {
this.thumb = new PhotoSize(jsonObject.getJSONObject(THUMB_FIELD));
} else {
this.thumb = null;
}
this.fileSize = jsonObject.optInt(FILESIZE_FIELD, 0);
}
}

18
src/main/java/org/telegram/api/Video.java

@ -32,9 +32,6 @@ public class Video {
public static final String FILESIZE_FIELD = "file_size";
@JsonProperty(FILESIZE_FIELD)
private Integer fileSize; ///< Optional. File size
public static final String CAPTION_FIELD = "caption";
@JsonProperty(CAPTION_FIELD)
private String caption; ///< Optional. Text description of the video (usually empty)
public Video() {
super();
@ -45,10 +42,13 @@ public class Video {
this.width = jsonObject.getInt(WIDTH_FIELD);
this.height = jsonObject.getInt(HEIGHT_FIELD);
this.duration = jsonObject.getInt(DURATION_FIELD);
this.thumb = new PhotoSize(jsonObject.getJSONObject(THUMB_FIELD));
if (jsonObject.has(THUMB_FIELD)) {
this.thumb = new PhotoSize(jsonObject.getJSONObject(THUMB_FIELD));
} else {
this.thumb = null;
}
this.mimeType = jsonObject.optString(MIMETYPE_FIELD, "");
this.fileSize = jsonObject.optInt(FILESIZE_FIELD, 0);
this.caption = jsonObject.optString(CAPTION_FIELD, "");
}
public Integer getWidth() {
@ -106,12 +106,4 @@ public class Video {
public void setFileSize(Integer fileSize) {
this.fileSize = fileSize;
}
public String getCaption() {
return caption;
}
public void setCaption(String caption) {
this.caption = caption;
}
}

87
src/main/java/org/telegram/database/CreationStrings.java

@ -7,9 +7,9 @@ package org.telegram.database;
* @date 15 of May of 2015
*/
public class CreationStrings {
public static final int version = 3;
public static final int version = 6;
public static final String createVersionTable = "CREATE TABLE IF NOT EXISTS Versions(ID INTEGER PRIMARY KEY AUTO_INCREMENT, Version INTEGER);";
public static final String insertCurrentVersion = "INSERT IGNORE INTO Versions (Version) VALUES(" + version + ");";
public static final String insertCurrentVersion = "INSERT IGNORE INTO Versions (Version) VALUES(%d);";
public static final String createFilesTable = "CREATE TABLE IF NOT EXISTS Files (fileId VARCHAR(100) PRIMARY KEY, userId INTEGER NOT NULL, caption TEXT NOT NULL)";
public static final String createUsersForFilesTable = "CREATE TABLE IF NOT EXISTS FilesUsers (userId INTEGER PRIMARY KEY, status INTEGER NOT NULL DEFAULT 0)";
public static final String createRecentWeatherTable = "CREATE TABLE IF NOT EXISTS RecentWeather (ID INTEGER PRIMARY KEY AUTO_INCREMENT, userId INTEGER NOT NULL, " +
@ -17,77 +17,14 @@ public class CreationStrings {
"CONSTRAINT unique_cistyuser UNIQUE (userId,cityId))";
public static final String createDirectionsDatabase = "CREATE TABLE IF NOT EXISTS Directions (userId INTEGER PRIMARY KEY, status INTEGER NOT NULL, " +
"messageId INTEGER NOT NULL DEFAULT 0, origin VARCHAR(100));";
/*public static final String createOperatingSystemsVersion = "CREATE TABLE IF NOT EXISTS OperatingSystems (operatingSystem VARCHAR(20) PRIMARY KEY);";
public static final String createLanguagesTable = "CREATE TABLE IF NOT EXISTS Languages(languageCode VARCHAR(6) PRIMARY KEY, languageName VARCHAR(30) NOT NULL);";
public static final String insertEnglishLanguage = "INSERT IGNORE INTO Languages (languageCode, languageName) VALUES('en', 'English');";
public static final String insertPortugueseLanguage = "INSERT IGNORE INTO Languages (languageCode, languageName) VALUES('pt', 'Portuguese');";
public static final String insertItalianLanguage = "INSERT IGNORE INTO Languages (languageCode, languageName) VALUES('it', 'Italian');";
public static final String createCountriesTable = "CREATE TABLE IF NOT EXISTS Countries(countryCode VARCHAR(6) PRIMARY KEY, name VARCHAR(20) NOT NULL);";
public static final String createLoginTable = "CREATE TABLE IF NOT EXISTS Logins(username VARCHAR(30) PRIMARY KEY, password VARCHAR(30) NOT NULL, " +
"hash VARCHAR(130) NOT NULL, securityLevel INTEGER DEFAULT 0);";
public static final String createLanguagesPerCountryTable = "CREATE TABLE IF NOT EXISTS LanguagesPerCountry( countryCode VARCHAR(6) PRIMARY KEY, firstLanguage VARCHAR(6) NOT NULL, " +
"secondLanguage VARCHAR(6) DEFAULT NULL, FOREIGN KEY (firstLanguage) REFERENCES Languages (languageCode) ON UPDATE CASCADE ON DELETE CASCADE, " +
"FOREIGN KEY (secondLanguage) REFERENCES Languages (languageCode) ON UPDATE CASCADE ON DELETE CASCADE);";
public static final String createUsersTable = "CREATE TABLE IF NOT EXISTS Users(userId INTEGER NOT NULL, bot INTEGER NOT NULL, needVolunteer BOOLEAN NOT NULL, phone VARCHAR(15) DEFAULT NULL, firstName VARCHAR(100) NOT NULL, " +
"lastName VARCHAR(100) NOT NULL, userName VARCHAR(100) DEFAULT NULL, isContact BOOLEAN NOT NULL, lastAnswer DATETIME, userHash VARCHAR(40) NOT NULL, lastScore FLOAT, hashtag VARCHAR(15), countryCode VARCHAR(6), denied INTEGER NOT NULL DEFAULT 0, " +
"customCommand VARCHAR(60) DEFAULT NULL, deleted BOOLEAN NOT NULL DEFAULT FALSE, " +
"CONSTRAINT `usersCountryCode` FOREIGN KEY (countryCode) REFERENCES Countries(countryCode) ON UPDATE CASCADE ON DELETE CASCADE, " +
"CONSTRAINT `userPrimaryKey` PRIMARY KEY(userId,bot));";
public static final String createAnswersTable = "CREATE TABLE IF NOT EXISTS AnswersXXXX (ID INTEGER PRIMARY KEY AUTO_INCREMENT, name VARCHAR(250) NOT NULL," +
"content VARCHAR(2000) NOT NULL, operatingSystem VARCHAR(20) NOT NULL, appVersion VARCHAR(10)," +
"CONSTRAINT `answersOSXXXX` FOREIGN KEY (operatingSystem) REFERENCES OperatingSystems(operatingSystem) ON UPDATE CASCADE ON DELETE CASCADE);";
public static final String insertEmptyAnswer = "INSERT IGNORE INTO AnswersXXXX (name, content, operatingSystem, appVersion, ID) VALUES ('Empty Answer','','All','',100);";
public static final String insertNotFoundAnswer = "INSERT IGNORE INTO AnswersXXXX (name, content, operatingSystem, appVersion, ID) VALUES ('Not found','','All','',99);";
public static final String createHistoryTable = "CREATE TABLE IF NOT EXISTS History( ID INTEGER PRIMARY KEY AUTO_INCREMENT, userId INTEGER NOT NULL, date DATETIME NOT NULL, answerId INTEGER NOT NULL, " +
"languageCode VARCHAR(6) NOT NULL, CONSTRAINT `historyUserId` FOREIGN KEY (userId) REFERENCES Users(userId) ON UPDATE CASCADE ON DELETE CASCADE, " +
"CONSTRAINT `historyLanguageCode` FOREIGN KEY (languageCode) REFERENCES Languages(languageCode) ON UPDATE CASCADE ON DELETE CASCADE);";
public static final String createQuestionsTable = "CREATE TABLE IF NOT EXISTS QuestionsXXXX (ID INTEGER PRIMARY KEY AUTO_INCREMENT, content VARCHAR(300) NOT NULL, " +
"languageCode VARCHAR(6) NOT NULL, answerAll INTEGER DEFAULT NULL, answerIos INTEGER DEFAULT NULL, answerWebogram INTEGER DEFAULT NULL, answerAndroid INTEGER DEFAULT NULL, " +
"answerOsx INTEGER DEFAULT NULL, answerDesktop INTEGER DEFAULT NULL, answerWP INTEGER DEFAULT NULL, " +
"CONSTRAINT `questionsAnswerAllXXXX` FOREIGN KEY (answerAll) REFERENCES AnswersXXXX(ID) ON UPDATE CASCADE ON DELETE CASCADE, " +
"CONSTRAINT `questionsAnswerIosXXXX` FOREIGN KEY (answerIos) REFERENCES AnswersXXXX(ID) ON UPDATE CASCADE ON DELETE CASCADE, " +
"CONSTRAINT `questionsAnswerWebogramXXXX` FOREIGN KEY (answerWebogram) REFERENCES AnswersXXXX(ID) ON UPDATE CASCADE ON DELETE CASCADE, " +
"CONSTRAINT `questionsAnswerAndroidXXXX` FOREIGN KEY (answerAndroid) REFERENCES AnswersXXXX(ID) ON UPDATE CASCADE ON DELETE CASCADE, " +
"CONSTRAINT `questionsAnswerOsxXXXX` FOREIGN KEY (answerOsx) REFERENCES AnswersXXXX(ID) ON UPDATE CASCADE ON DELETE CASCADE, " +
"CONSTRAINT `questionsAnswerDesktopXXXX` FOREIGN KEY (answerDesktop) REFERENCES AnswersXXXX(ID) ON UPDATE CASCADE ON DELETE CASCADE, " +
"CONSTRAINT `questionsAnswerWPXXXX` FOREIGN KEY (answerWP) REFERENCES AnswersXXXX(ID) ON UPDATE CASCADE ON DELETE CASCADE);";
public static final String createTrelloTable = "CREATE TABLE IF NOT EXISTS trello (shortLink VARCHAR(10) PRIMARY KEY NOT NULL, listName VARCHAR(20) NOT NULL, listId VARCHAR(30), " +
"closed BOOLEAN NOT NULL, creationDate DATETIME NOT NULL, notificationDate DATETIME NOT NULL, affectedUserCount INTEGER NOT NULL DEFAULT 0, tittle VARCHAR(100) NOT NULL, " +
"description TEXT NOT NULL);";
public static final String createTemplatesTable = "CREATE TABLE IF NOT EXISTS Templates (id INTEGER PRIMARY KEY AUTO_INCREMENT, hash VARCHAR(130) NOT NULL, " +
"languageCode VARCHAR(8), content TEXT);";
public static final String createTemplatesLogTable = "CREATE TABLE IF NOT EXISTS TemplatesLog (id INTEGER PRIMARY KEY AUTO_INCREMENT, hash VARCHAR(130) NOT NULL, type INTEGER, content TEXT);";
public static final String createTemplatesFileTable = "CREATE TABLE IF NOT EXISTS TemplatesFile (id INTEGER PRIMARY KEY AUTO_INCREMENT, hash VARCHAR(130) NOT NULL, date DATETIME, languageCode VARCHAR(8)," +
" CONSTRAINT unique_filelanguage UNIQUE (hash,languageCode));";
public static final String createFiltersTable = "create table if not exists Filters (filterId INTEGER PRIMARY KEY AUTO_INCREMENT," +
" words VARCHAR(300) NOT NULL, languageCode VARCHAR(6) NOT NULL," +
" CONSTRAINT `filtersLanguageCode` FOREIGN KEY (languageCode) REFERENCES Languages(languageCode) ON UPDATE CASCADE ON DELETE CASCADE" +
");";
public static final String createMessagesDiscardedTable = "create table if not exists MessagesDiscarded (id INTEGER PRIMARY KEY AUTO_INCREMENT," +
" userId INTEGER NOT NULL, filterId INTEGER NOT NULL, message TEXT NOT NULL, date TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," +
" partial BOOLEAN NOT NULL DEFAULT false, CONSTRAINT `messagesDiscardedUserId` FOREIGN KEY (userId) REFERENCES Users(userId) ON UPDATE CASCADE ON DELETE CASCADE," +
" CONSTRAINT `messageDiscardedFilterId` FOREIGN KEY (filterId) REFERENCES Filters(filterId) ON UPDATE CASCADE ON DELETE CASCADE);";
public static final String createMessagesAnsweredTable = "create table if not exists MessagesAnswered (id INTEGER PRIMARY KEY AUTO_INCREMENT," +
" userId INTEGER NOT NULL, answer INTEGER NOT NULL, message TEXT NOT NULL, matchValue FLOAT NOT NULL, date TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," +
" partial BOOLEAN NOT NULL DEFAULT false, CONSTRAINT `messagesAnswerdUserId` FOREIGN KEY (userId) REFERENCES Users(userId) ON UPDATE CASCADE ON DELETE CASCADE);";
public static final String createChatListTable = "create table if not exists Chats (chatId INTEGER PRIMARY KEY NOT NULL, " +
"title VARCHAR(50) NOT NULL);";
public static final String createChatsStatsTable = "create table if not exists ChatStats (id INTEGER PRIMARY KEY AUTO_INCREMENT," +
" userId INTEGER NOT NULL, chatId INTEGER NOT NULL, date TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," +
" forwarded BOOLEAN NOT NULL DEFAULT false, type INTEGER NOT NULL," +
"CONSTRAINT `chatsStatsUserId` FOREIGN KEY (userId) REFERENCES Users(userId) ON UPDATE CASCADE ON DELETE CASCADE, " +
"CONSTRAINT `chatsStatsChatId` FOREIGN KEY (chatId) REFERENCES Chats(chatId) ON UPDATE CASCADE ON DELETE CASCADE);";
public static volatile List<String> operatingSystems = new ArrayList<>();
static {
operatingSystems.add("All");
operatingSystems.add("iOS");
operatingSystems.add("Webogram");
operatingSystems.add("Android");
operatingSystems.add("OSX");
operatingSystems.add("Desktop");
operatingSystems.add("WP");
}*/
public static final String createLastUpdateDatabase = "CREATE TABLE IF NOT EXISTS LastUpdate (token VARCHAR(125) PRIMARY KEY, updateId INTEGER NOT NULL DEFAULT -1);";
public static final String createUserLanguageDatabase = "CREATE TABLE IF NOT EXISTS UserLanguage (userId INTEGER PRIMARY KEY, languageCode VARCHAR(10) NOT NULL)";
public static final String createUserWeatherOptionDatabase = "CREATE TABLE IF NOT EXISTS UserWeatherOptions (userId INTEGER PRIMARY KEY, languageCode VARCHAR(10) NOT NULL DEFAULT 'en', " +
"units VARCHAR(10) NOT NULL DEFAULT 'metric')";
public static final String createWeatherStateTable = "CREATE TABLE IF NOT EXISTS WeatherState (userId INTEGER NOT NULL, chatId INTEGER NOT NULL, state INTEGER NOT NULL DEFAULT 0, " +
"languageCode VARCHAR(10) NOT NULL DEFAULT 'en', " +
"CONSTRAINT `watherPrimaryKey` PRIMARY KEY(userId,chatId));";
public static final String createWeatherAlertTable = "CREATE TABLE IF NOT EXISTS WeatherAlert (id INTEGER PRIMARY KEY AUTO_INCREMENT, userId INTEGER NOT NULL, cityId INTEGER NOT NULL, " +
"cityName VARCHAR(60) NOT NULL, time INTEGER NOT NULL DEFAULT -1, CONSTRAINT unique_cityNameAlert UNIQUE (userId, cityName)," +
"CONSTRAINT unique_cityIdAlert UNIQUE (userId, cityId));";
}

273
src/main/java/org/telegram/database/DatabaseManager.java

@ -8,12 +8,16 @@
package org.telegram.database;
import org.telegram.services.BotLogger;
import org.telegram.structure.WeatherAlert;
import org.telegram.updateshandlers.WeatherHandlers;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* @author Ruben Bermudez
@ -73,6 +77,15 @@ public class DatabaseManager {
if (currentVersion == 2) {
currentVersion = updateToVersion3();
}
if (currentVersion == 3) {
currentVersion = updateToVersion4();
}
if (currentVersion == 4) {
currentVersion = updateToVersion5();
}
if (currentVersion == 5) {
currentVersion = updateToVersion6();
}
connetion.commitTransaction();
} catch (SQLException e) {
log.error(e);
@ -81,23 +94,47 @@ public class DatabaseManager {
private int updateToVersion2() throws SQLException {
connetion.executeQuery(CreationStrings.createRecentWeatherTable);
connetion.executeQuery("INSERT IGNORE INTO Versions (Version) VALUES(2);");
connetion.executeQuery(String.format(CreationStrings.insertCurrentVersion, 2));
return 2;
}
private int updateToVersion3() throws SQLException {
connetion.executeQuery(CreationStrings.createDirectionsDatabase);
connetion.executeQuery("INSERT IGNORE INTO Versions (Version) VALUES(3);");
connetion.executeQuery(String.format(CreationStrings.insertCurrentVersion, 3));
return 2;
}
private int updateToVersion4() throws SQLException {
connetion.executeQuery(CreationStrings.createLastUpdateDatabase);
connetion.executeQuery(String.format(CreationStrings.insertCurrentVersion, 4));
return 4;
}
private int updateToVersion5() throws SQLException {
connetion.executeQuery(CreationStrings.createUserLanguageDatabase);
connetion.executeQuery(String.format(CreationStrings.insertCurrentVersion, 5));
return 5;
}
private int updateToVersion6() throws SQLException {
connetion.executeQuery(CreationStrings.createWeatherStateTable);
connetion.executeQuery(CreationStrings.createUserWeatherOptionDatabase);
connetion.executeQuery(CreationStrings.createWeatherAlertTable);
connetion.executeQuery(String.format(CreationStrings.insertCurrentVersion, 6));
return 6;
}
private int createNewTables() throws SQLException {
connetion.executeQuery(CreationStrings.createVersionTable);
connetion.executeQuery(CreationStrings.createFilesTable);
connetion.executeQuery(CreationStrings.insertCurrentVersion);
connetion.executeQuery(String.format(CreationStrings.insertCurrentVersion, CreationStrings.version));
connetion.executeQuery(CreationStrings.createUsersForFilesTable);
connetion.executeQuery(CreationStrings.createRecentWeatherTable);
connetion.executeQuery(CreationStrings.createDirectionsDatabase);
connetion.executeQuery(CreationStrings.createUserLanguageDatabase);
connetion.executeQuery(CreationStrings.createWeatherStateTable);
connetion.executeQuery(CreationStrings.createUserWeatherOptionDatabase);
connetion.executeQuery(CreationStrings.createWeatherAlertTable);
return CreationStrings.version;
}
@ -214,14 +251,14 @@ public class DatabaseManager {
return updatedRows > 0;
}
public HashMap<Integer,String> getRecentWeather(Integer userId) {
HashMap<Integer,String> recentWeather = new HashMap<>();
public List<String> getRecentWeather(Integer userId) {
List<String> recentWeather = new ArrayList<>();
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("select * FROM RecentWeather WHERE userId=?");
final PreparedStatement preparedStatement = connetion.getPreparedStatement("select * FROM RecentWeather WHERE userId=? order by date desc");
preparedStatement.setInt(1, userId);
final ResultSet result = preparedStatement.executeQuery();
while (result.next()) {
recentWeather.put(result.getInt("cityId"), result.getString("cityName"));
recentWeather.add(result.getString("cityName"));
}
} catch (SQLException e) {
e.printStackTrace();
@ -317,4 +354,226 @@ public class DatabaseManager {
}
return updatedRows > 0;
}
public boolean putLastUpdate(String token, Integer updateId) {
int updatedRows = 0;
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("REPLACE INTO LastUpdate (token, updateId) VALUES(?, ?)");
preparedStatement.setString(1, token);
preparedStatement.setInt(2, updateId);
updatedRows = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return updatedRows > 0;
}
public Integer getLastUpdate(String token) {
Integer updateId = -1;
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("SELECT updateId FROM LastUpdate WHERE token = ?");
preparedStatement.setString(1, token);
final ResultSet result = preparedStatement.executeQuery();
if (result.next()) {
updateId = result.getInt("updateId");
}
} catch (SQLException e) {
e.printStackTrace();
}
return updateId;
}
public String getUserLanguage(Integer userId) {
String languageCode = "en";
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("SELECT languageCode FROM UserLanguage WHERE userId = ?");
preparedStatement.setInt(1, userId);
final ResultSet result = preparedStatement.executeQuery();
if (result.next()) {
languageCode = result.getString("languageCode");
}
} catch (SQLException e) {
e.printStackTrace();
}
return languageCode;
}
public boolean putUserLanguage(Integer userId, String language) {
int updatedRows = 0;
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("REPLACE INTO UserLanguage (userId, languageCode) VALUES(?, ?)");
preparedStatement.setInt(1, userId);
preparedStatement.setString(2, language);
updatedRows = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return updatedRows > 0;
}
public int getWeatherState(Integer userId, Integer chatId) {
int state = 0;
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("SELECT state FROM WeatherState WHERE userId = ? AND chatId = ?");
preparedStatement.setInt(1, userId);
preparedStatement.setInt(2, chatId);
final ResultSet result = preparedStatement.executeQuery();
if (result.next()) {
state = result.getInt("state");
}
} catch (SQLException e) {
e.printStackTrace();
}
return state;
}
public boolean insertWeatherState(Integer userId, Integer chatId, int state) {
int updatedRows = 0;
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("REPLACE INTO WeatherState (userId, chatId, state) VALUES (?, ?, ?)");
preparedStatement.setInt(1, userId);
preparedStatement.setInt(2, chatId);
preparedStatement.setInt(3, state);
updatedRows = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return updatedRows > 0;
}
public Integer getRecentWeatherIdByCity(Integer userId, String city) {
Integer cityId = null;
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("select cityId FROM RecentWeather WHERE userId=? AND cityName=?");
preparedStatement.setInt(1, userId);
preparedStatement.setString(2, city);
final ResultSet result = preparedStatement.executeQuery();
if (result.next()) {
cityId = result.getInt("cityId");
}
} catch (SQLException e) {
e.printStackTrace();
}
return cityId;
}
public String[] getUserWeatherOptions(Integer userId) {
String[] options = new String[] {"en", "metric"};
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("SELECT * FROM UserWeatherOptions WHERE userId = ?");
preparedStatement.setInt(1, userId);
final ResultSet result = preparedStatement.executeQuery();
if (result.next()) {
options[0] = result.getString("languageCode");
options[1] = result.getString("units");
} else {
addNewUserWeatherOptions(userId);
}
} catch (SQLException e) {
e.printStackTrace();
}
return options;
}
private boolean addNewUserWeatherOptions(Integer userId) {
int updatedRows = 0;
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("INSERT INTO UserWeatherOptions (userId) VALUES (?)");
preparedStatement.setInt(1, userId);
updatedRows = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return updatedRows > 0;
}
public boolean putUserWeatherLanguageOption(Integer userId, String language) {
int updatedRows = 0;
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("UPDATE UserWeatherOptions SET languageCode = ? WHERE userId = ?");
preparedStatement.setString(1, language);
preparedStatement.setInt(2, userId);
updatedRows = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return updatedRows > 0;
}
public boolean putUserWeatherUnitsOption(Integer userId, String units) {
int updatedRows = 0;
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("UPDATE UserWeatherOptions SET units = ? WHERE userId = ?");
preparedStatement.setString(1, units);
preparedStatement.setInt(2, userId);
updatedRows = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return updatedRows > 0;
}
public boolean createNewWeatherAlert(int userId, Integer cityId, String cityName) {
int updatedRows = 0;
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("INSERT INTO WeatherAlert (userId, cityId, cityName) VALUES (?,?,?)");
preparedStatement.setInt(1, userId);
preparedStatement.setInt(2, cityId);
preparedStatement.setString(3, cityName);
updatedRows = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return updatedRows > 0;
}
public List<String> getAlertCitiesNameByUser(int userId) {
List<String> alertCitiesNames = new ArrayList<>();
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("select cityName FROM WeatherAlert WHERE userId=?");
preparedStatement.setInt(1, userId);
final ResultSet result = preparedStatement.executeQuery();
while (result.next()) {
alertCitiesNames.add(result.getString("cityName"));
}
} catch (SQLException e) {
e.printStackTrace();
}
return alertCitiesNames;
}
public boolean deleteAlertCity(Integer userId, String cityName) {
int updatedRows = 0;
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("DELETE FROM WeatherAlert WHERE userId=? AND cityName=?;");
preparedStatement.setInt(1, userId);
preparedStatement.setString(2, cityName);
updatedRows = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return updatedRows > 0;
}
public List<WeatherAlert> getAllAlerts() {
List<WeatherAlert> allAlerts = new ArrayList<>();
try {
final PreparedStatement preparedStatement = connetion.getPreparedStatement("select * FROM WeatherAlert");
final ResultSet result = preparedStatement.executeQuery();
while (result.next()) {
WeatherAlert weatherAlert = new WeatherAlert();
weatherAlert.setId(result.getInt("id"));
weatherAlert.setUserId(result.getInt("userId"));
weatherAlert.setCityId(result.getInt("cityId"));
allAlerts.add(weatherAlert);
}
} catch (SQLException e) {
e.printStackTrace();
}
return allAlerts;
}
}

56
src/main/java/org/telegram/methods/SendSticker.java

@ -11,7 +11,7 @@ import org.telegram.api.ReplyKeyboard;
public class SendSticker {
public static final String PATH = "sendsticker";
public static final String CHATID_FIELD = "document";
public static final String CHATID_FIELD = "chat_id";
private Integer chatId; ///< Unique identifier for the message recepient — User or GroupChat id
public static final String STICKER_FIELD = "sticker";
private String sticker; ///< Sticker file to send. file_id as String to resend a sticker that is already on the Telegram servers
@ -19,4 +19,58 @@ public class SendSticker {
private Integer replayToMessageId; ///< Optional. If the message is a reply, ID of the original message
public static final String REPLYMARKUP_FIELD = "reply_markup";
private ReplyKeyboard replayMarkup; ///< Optional. JSON-serialized object for a custom reply keyboard
private boolean isNewSticker;
private String stickerName;
public SendSticker() {
super();
}
public Integer getChatId() {
return chatId;
}
public void setChatId(Integer chatId) {
this.chatId = chatId;
}
public String getSticker() {
return sticker;
}
public Integer getReplayToMessageId() {
return replayToMessageId;
}
public void setReplayToMessageId(Integer replayToMessageId) {
this.replayToMessageId = replayToMessageId;
}
public ReplyKeyboard getReplayMarkup() {
return replayMarkup;
}
public void setReplayMarkup(ReplyKeyboard replayMarkup) {
this.replayMarkup = replayMarkup;
}
public void setSticker(String sticker) {
this.sticker = sticker;
this.isNewSticker = false;
}
public void setSticker(String sticker, String stickerName) {
this.sticker = sticker;
this.isNewSticker = true;
this.stickerName = stickerName;
}
public boolean isNewSticker() {
return isNewSticker;
}
public String getStickerName() {
return stickerName;
}
}

4
src/main/java/org/telegram/methods/SendVideo.java

@ -17,6 +17,10 @@ public class SendVideo {
private Integer chatId; ///< Unique identifier for the message recepient — User or GroupChat id
public static final String VIDEO_FIELD = "video";
private String video; ///< Video to send. file_id as String to resend a video that is already on the Telegram servers
public static final String DURATION_FIELD = "duration";
private String duration; ///< Optional. Duration of sent video in seconds
public static final String CAPTION_FIELD = "caption";
private String caption; ///< OptionaL. Video caption (may also be used when resending videos by file_id).
public static final String REPLYTOMESSAGEID_FIELD = "reply_to_message_id";
private Integer replayToMessageId; ///< Optional. If the message is a reply, ID of the original message
public static final String REPLYMARKUP_FIELD = "reply_markup";

257
src/main/java/org/telegram/services/BotLogger.java

@ -4,76 +4,83 @@ import org.telegram.BuildVars;
import javax.validation.constraints.NotNull;
import java.io.*;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author Ruben Bermudez
* @version 2.0
* @brief Logger to file
* @version 1.0
* @brief Logger
* @date 21/01/15
*/
public class BotLogger {
private static final Object lockToWrite = new Object();
private volatile Object lockToWrite = new Object();
private final Logger logger;
private static volatile PrintWriter logginFile;
private Calendar lastFileDate;
private static volatile String currentFileName;
private static LoggerThread loggerThread = new LoggerThread();
private static volatile ConcurrentHashMap<String, BotLogger> instances = new ConcurrentHashMap<>();
private final Logger logger;
private LocalDateTime lastFileDate;
private final static ConcurrentLinkedQueue<String> logsToFile = new ConcurrentLinkedQueue<>();
private BotLogger(String classname) {
this.logger = Logger.getLogger(classname);
this.logger.setLevel(Level.ALL);
this.lastFileDate = LocalDateTime.now();
if (currentFileName == null || currentFileName.compareTo("") == 0) {
currentFileName = BuildVars.pathToLogs + dateFormatterForFileName(this.lastFileDate) + ".log";
try {
File file = new File(currentFileName);
if (file.exists()) {
logginFile = new PrintWriter(new BufferedWriter(new FileWriter(currentFileName, true)));
} else {
boolean created = file.createNewFile();
if (created) {
logginFile = new PrintWriter(new BufferedWriter(new FileWriter(currentFileName, true)));
} else {
throw new NullPointerException("File for loggin error");
}
}
} catch (IOException ignored) {
}
static {
}
loggerThread.start();
}
public static BotLogger getLogger(@NotNull String className) {
BotLogger currentInstance;
if (instances.containsKey(className)) {
currentInstance = instances.get(className);
} else {
if (!instances.containsKey(className)) {
synchronized (BotLogger.class) {
if (instances.containsKey(className)) {
currentInstance = instances.get(className);
} else {
if (!instances.containsKey(className)) {
BotLogger instance = new BotLogger(className);
instances.put(className, instance);
currentInstance = instance;
return instance;
} else {
return instances.get(className);
}
}
} else {
return instances.get(className);
}
}
return currentInstance;
private BotLogger(String classname) {
logger = Logger.getLogger(classname);
logger.setLevel(Level.ALL);
ConsoleHandler handler = new ConsoleHandler();
handler.setLevel(Level.ALL);
logger.addHandler(handler);
lastFileDate = new GregorianCalendar();
if (currentFileName == null || currentFileName.length() == 0) {
currentFileName = BuildVars.pathToLogs + dateFormaterForFileName(lastFileDate) + ".log";
try {
File file = new File(currentFileName);
if (!file.exists()) {
file.createNewFile();
}
logginFile = new PrintWriter(new BufferedWriter(new FileWriter(currentFileName, true)));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void log(@NotNull Level level, String msg) {
this.logger.log(level, msg);
logger.log(level, msg);
logToFile(level, msg);
}
public void severe(String msg) {
this.logger.severe(msg);
logger.severe(msg);
logToFile(Level.SEVERE, msg);
}
@ -94,49 +101,49 @@ public class BotLogger {
}
public void warning(String msg) {
this.logger.warning(msg);
logger.warning(msg);
logToFile(Level.WARNING, msg);
}
public void info(String msg) {
this.logger.info(msg);
logger.info(msg);
logToFile(Level.INFO, msg);
}
public void config(String msg) {
this.logger.config(msg);
logger.config(msg);
logToFile(Level.CONFIG, msg);
}
public void fine(String msg) {
this.logger.fine(msg);
logger.fine(msg);
logToFile(Level.FINE, msg);
}
public void finer(String msg) {
this.logger.finer(msg);
logger.finer(msg);
logToFile(Level.FINER, msg);
}
public void finest(String msg) {
this.logger.finest(msg);
logger.finest(msg);
logToFile(Level.FINEST, msg);
}
public void log(@NotNull Level level, @NotNull Throwable throwable) {
this.logger.log(level, "Exception", throwable);
throwable.printStackTrace();
logToFile(level, throwable);
}
public void log(@NotNull Level level, String msg, Throwable thrown) {
this.logger.log(level, msg, thrown);
logToFile(level, msg, thrown);
logger.log(level, msg, thrown);
logToFile(level, msg ,thrown);
}
public void severe(@NotNull Throwable throwable) {
@ -227,105 +234,120 @@ public class BotLogger {
log(Level.FINER, msg, throwable);
}
private boolean isCurrentDate(LocalDateTime dateTime) {
return dateTime.toLocalDate().isEqual(this.lastFileDate.toLocalDate());
private boolean isCurrentDate(Calendar calendar) {
if (calendar.get(Calendar.DAY_OF_MONTH) != lastFileDate.get(Calendar.DAY_OF_MONTH)) {
return false;
}
if (calendar.get(Calendar.MONTH) != lastFileDate.get(Calendar.MONTH)) {
return false;
}
if (calendar.get(Calendar.YEAR) != lastFileDate.get(Calendar.YEAR)) {
return false;
}
return true;
}
private String dateFormatterForFileName(@NotNull LocalDateTime dateTime) {
private String dateFormaterForFileName(@NotNull Calendar calendar) {
String dateString = "";
dateString += dateTime.getDayOfMonth();
dateString += dateTime.getMonthValue();
dateString += dateTime.getYear();
dateString += calendar.get(Calendar.DAY_OF_MONTH);
dateString += calendar.get(Calendar.MONTH) + 1;
dateString += calendar.get(Calendar.YEAR);
return dateString;
}
private String dateFormatterForLogs(@NotNull LocalDateTime dateTime) {
private String dateFormaterForLogs(@NotNull Calendar calendar) {
String dateString = "[";
dateString += dateTime.getDayOfMonth() + "_";
dateString += dateTime.getMonthValue() + "_";
dateString += dateTime.getYear() + "_";
dateString += dateTime.getHour() + ":";
dateString += dateTime.getMinute() + ":";
dateString += dateTime.getSecond();
dateString += calendar.get(Calendar.DAY_OF_MONTH) + "_";
dateString += (calendar.get(Calendar.MONTH) + 1) + "_";
dateString += calendar.get(Calendar.YEAR) + "_";
dateString += calendar.get(Calendar.HOUR_OF_DAY) + "_";
dateString += calendar.get(Calendar.MINUTE) + ":";
dateString += calendar.get(Calendar.SECOND);
dateString += "] ";
return dateString;
}
private void updateAndCreateFile(LocalDateTime dateTime) {
if (!isCurrentDate(dateTime)) {
this.lastFileDate = LocalDateTime.now();
currentFileName = BuildVars.pathToLogs + dateFormatterForFileName(this.lastFileDate) + ".log";
try {
logginFile.flush();
logginFile.close();
File file = new File(currentFileName);
if (file.exists()) {
logginFile = new PrintWriter(new BufferedWriter(new FileWriter(currentFileName, true)));
} else {
boolean created = file.createNewFile();
if (created) {
logginFile = new PrintWriter(new BufferedWriter(new FileWriter(currentFileName, true)));
} else {
throw new NullPointerException("Error updating log file");
}
}
} catch (IOException ignored) {
private void updateAndCreateFile(Calendar calendar) {
if (isCurrentDate(calendar)) {
return;
}
lastFileDate = new GregorianCalendar();
currentFileName = BuildVars.pathToLogs + dateFormaterForFileName(lastFileDate) + ".log";
try {
logginFile.flush();
logginFile.close();
File file = new File(currentFileName);
if (!file.exists()) {
file.createNewFile();
}
logginFile = new PrintWriter(new BufferedWriter(new FileWriter(currentFileName, true)));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void logToFile(@NotNull Level level, Throwable throwable) {
if (isLoggable(level)) {
synchronized (lockToWrite) {
LocalDateTime currentDate = LocalDateTime.now();
String dateForLog = dateFormatterForLogs(currentDate);
updateAndCreateFile(currentDate);
logThrowableToFile(level, throwable, dateForLog);
}
if (!isLoggable(level)){
return;
}
synchronized (lockToWrite) {
Calendar currentDate = new GregorianCalendar();
String dateForLog = dateFormaterForLogs(currentDate);
updateAndCreateFile(currentDate);
logThrowableToFile(level, throwable, dateForLog);
}
}
private void logToFile(@NotNull Level level, String msg) {
if (isLoggable(level)) {
synchronized (lockToWrite) {
LocalDateTime currentDate = LocalDateTime.now();
updateAndCreateFile(currentDate);
String dateForLog = dateFormatterForLogs(currentDate);
logMsgToFile(level, msg, dateForLog);
}
if (!isLoggable(level)){
return;
}
synchronized (lockToWrite) {
Calendar currentDate = new GregorianCalendar();
updateAndCreateFile(currentDate);
String dateForLog = dateFormaterForLogs(currentDate);
logMsgToFile(level, msg, dateForLog);
}
}
private void logToFile(Level level, String msg, Throwable throwable) {
if (!isLoggable(level)) {
if (!isLoggable(level)){
return;
}
synchronized (lockToWrite) {
LocalDateTime currentDate = LocalDateTime.now();
Calendar currentDate = new GregorianCalendar();
updateAndCreateFile(currentDate);
String dateForLog = dateFormatterForLogs(currentDate);
String dateForLog = dateFormaterForLogs(currentDate);
logMsgToFile(level, msg, dateForLog);
logThrowableToFile(level, throwable, dateForLog);
}
}
private void logMsgToFile(Level level, String msg, String dateForLog) {
dateForLog += level.toString() + " - " + msg;
logginFile.println(dateForLog);
logginFile.flush();
dateForLog += " [" + logger.getName() + "]" + level.toString() + " - " + msg;
logsToFile.add(dateForLog);
synchronized (logsToFile) {
logsToFile.notifyAll();
}
}
private void logThrowableToFile(Level level, Throwable throwable, String dateForLog) {
logginFile.println(dateForLog + level.getName() + " - " + throwable);
String throwableLog = dateForLog + level.getName() + " - " + throwable + "\n";
for (StackTraceElement element : throwable.getStackTrace()) {
logginFile.println("\tat " + element);
throwableLog += "\tat " + element + "\n";
}
logsToFile.add(throwableLog);
synchronized (logsToFile) {
logsToFile.notifyAll();
}
logginFile.flush();
}
private boolean isLoggable(Level level) {
return this.logger.isLoggable(level) && BuildVars.debug;
return logger.isLoggable(level) && BuildVars.debug;
}
@Override
@ -334,4 +356,33 @@ public class BotLogger {
logginFile.close();
super.finalize();
}
private static class LoggerThread extends Thread {
@Override
public void run() {
setPriority(Thread.MIN_PRIORITY);
while(true) {
ConcurrentLinkedQueue<String> stringsToLog = new ConcurrentLinkedQueue<>();
synchronized (logsToFile) {
if (logsToFile.isEmpty()) {
try {
logsToFile.wait();
} catch (InterruptedException e) {
return;
}
if (logsToFile.isEmpty()) {
continue;
}
}
stringsToLog.addAll(logsToFile);
logsToFile.clear();
}
for (String stringToLog: stringsToLog) {
logginFile.println(stringToLog);
}
logginFile.flush();
}
}
}
}

69
src/main/java/org/telegram/services/CustomTimerTask.java

@ -0,0 +1,69 @@
package org.telegram.services;
/**
* @author Ruben Bermudez
* @version 2.0
* @brief Task to be execute periodically
* @date 28/01/15
*/
public abstract class CustomTimerTask {
private String taskName = ""; ///< Task name
private int times = 1;
/**
* Constructor
*
* @param taskName Name of the task
*/
public CustomTimerTask(String taskName, int times) {
this.taskName = taskName;
this.times = times;
}
/**
* Get name
*
* @return name
*/
public String getTaskName() {
return this.taskName;
}
/**
* Set name
*
* @param taskName new name
*/
public void setTaskName(String taskName) {
this.taskName = taskName;
}
/**
* Getter for the times
*
* @return Remainint times the task must be executed
*/
public int getTimes() {
return this.times;
}
/**
* Setter for the times
*
* @param times Number of times the task must be executed
*/
public void setTimes(int times) {
this.times = times;
}
public void reduceTimes() {
if (this.times > 0) {
this.times -= 1;
}
}
/**
* @abstract Should contain the functionality of the task
*/
public abstract void execute();
}

63
src/main/java/org/telegram/services/DirectionsService.java

@ -17,6 +17,8 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
/**
* @author Ruben Bermudez
@ -25,9 +27,11 @@ import java.time.format.DateTimeFormatter;
* @date 20 of June of 2015
*/
public class DirectionsService {
private static volatile BotLogger log = BotLogger.getLogger(DirectionsService.class.getName());
private static final String BASEURL = "https://maps.googleapis.com/maps/api/directions/json"; ///< Base url for REST
private static final String APIIDEND = "&key=" + BuildVars.DirectionsApiKey;
private static final String PARAMS = "&language=en&units=metric";
private static final String PARAMS = "&language=@language@&units=metric";
private static final DateTimeFormatter dateFormaterFromDate = DateTimeFormatter.ofPattern("dd/MM/yyyy"); ///< Date to text formater
private static volatile DirectionsService instance; ///< Instance of this class
@ -64,10 +68,11 @@ public class DirectionsService {
* @param destination Destination address
* @return Destinations
*/
public String getDirections(String origin, String destination) {
String responseToUser;
public List<String> getDirections(String origin, String destination, String language) {
final List<String> responseToUser = new ArrayList<>();
try {
String completURL = BASEURL + "?origin=" + getQuery(origin) + "&destination=" + getQuery(destination) + PARAMS + APIIDEND;
String completURL = BASEURL + "?origin=" + getQuery(origin) + "&destination=" +
getQuery(destination) + PARAMS.replace("@language@", language) + APIIDEND;
HttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
HttpGet request = new HttpGet(completURL);
HttpResponse response = client.execute(request);
@ -79,20 +84,22 @@ public class DirectionsService {
JSONObject jsonObject = new JSONObject(responseContent);
if (jsonObject.getString("status").equals("OK")) {
JSONObject route = jsonObject.getJSONArray("routes").getJSONObject(0);
responseToUser = route.getJSONArray("legs").getJSONObject(0).getString("start_address");
responseToUser += " is ";
responseToUser += route.getJSONArray("legs").getJSONObject(0).getJSONObject("distance").getString("text");
responseToUser += " away from ";
responseToUser += route.getJSONArray("legs").getJSONObject(0).getString("end_address"); // TODO Destination
responseToUser += " and it takes ";
responseToUser += route.getJSONArray("legs").getJSONObject(0).getJSONObject("duration").getString("text");
responseToUser += " to arrive there following these directions:\n\n";
responseToUser += getDirectionsSteps(route.getJSONArray("legs").getJSONObject(0).getJSONArray("steps"));
String startOfAddress = LocalisationService.getInstance().getString("directionsInit", language);
String partialResponseToUser = String.format(startOfAddress,
route.getJSONArray("legs").getJSONObject(0).getString("start_address"),
route.getJSONArray("legs").getJSONObject(0).getJSONObject("distance").getString("text"),
route.getJSONArray("legs").getJSONObject(0).getString("end_address"),
route.getJSONArray("legs").getJSONObject(0).getJSONObject("duration").getString("text")
);
responseToUser.add(partialResponseToUser);
responseToUser.addAll(getDirectionsSteps(
route.getJSONArray("legs").getJSONObject(0).getJSONArray("steps"), language));
} else {
responseToUser = "Directions not found between " + origin + " and " + destination;
responseToUser.add(LocalisationService.getInstance().getString("directionsNotFound", language));
}
} catch (IOException e) {
responseToUser = "Error fetching weather info";
} catch (Exception e) {
log.warning(e);
responseToUser.add(LocalisationService.getInstance().getString("errorFetchingDirections", language));
}
return responseToUser;
}
@ -101,24 +108,30 @@ public class DirectionsService {
return URLEncoder.encode(address, "UTF-8");
}
public String getDirectionsSteps(JSONArray steps) {
String stepsStringify = "";
private List<String> getDirectionsSteps(JSONArray steps, String language) {
List<String> stepsStringify = new ArrayList<>();
String partialStepsStringify = "";
for (int i = 0; i < steps.length(); i++) {
stepsStringify += i + ".\t" + getDirectionForStep(steps.getJSONObject(i)) + "\n\n";
String step = getDirectionForStep(steps.getJSONObject(i), language);
if (partialStepsStringify.length() > 1000) {
stepsStringify.add(partialStepsStringify);
partialStepsStringify = "";
}
partialStepsStringify += i + ".\t" + step + "\n\n";
}
if (!partialStepsStringify.isEmpty()) {
stepsStringify.add(partialStepsStringify);
}
return stepsStringify;
}
private String getDirectionForStep(JSONObject jsonObject) {
String direction = "";
private String getDirectionForStep(JSONObject jsonObject, String language) {
String direction = LocalisationService.getInstance().getString("directionsStep", language);
String htmlIntructions = Jsoup.parse(jsonObject.getString("html_instructions")).text();
String duration = jsonObject.getJSONObject("duration").getString("text");
String distance = jsonObject.getJSONObject("distance").getString("text");
direction += htmlIntructions + " ";
direction += " during ";
direction += duration;
direction += " (" + distance + ")";
direction = String.format(direction, htmlIntructions, duration, distance);
return direction;
}

188
src/main/java/org/telegram/services/Emoji.java

@ -0,0 +1,188 @@
package org.telegram.services;
/**
* @author Ruben Bermudez
* @version 1.0
* @brief Enumerate of emojis with unicode chars
* @date 02 of July of 2015
*/
public enum Emoji {
// Emoticones group
GRINNING_FACE_WITH_SMILING_EYES('\uD83D', '\uDE01'),
FACE_WITH_TEARS_OF_JOY('\uD83D', '\uDE02'),
SMILING_FACE_WITH_OPEN_MOUTH('\uD83D', '\uDE03'),
SMILING_FACE_WITH_OPEN_MOUTH_AND_SMILING_EYES('\uD83D', '\uDE04'),
SMILING_FACE_WITH_OPEN_MOUTH_AND_COLD_SWEAT('\uD83D', '\uDE05'),
SMILING_FACE_WITH_OPEN_MOUTH_AND_TIGHTLY_CLOSED_EYES('\uD83D', '\uDE06'),
WINKING_FACE('\uD83D', '\uDE09'),
SMILING_FACE_WITH_SMILING_EYES('\uD83D', '\uDE0A'),
FACE_SAVOURING_DELICIOUS_FOOD('\uD83D', '\uDE0B'),
RELIEVED_FACE('\uD83D', '\uDE0C'),
SMILING_FACE_WITH_HEART_SHAPED_EYES('\uD83D', '\uDE0D'),
SMIRKING_FACE('\uD83D', '\uDE0F'),
UNAMUSED_FACE('\uD83D', '\uDE12'),
FACE_WITH_COLD_SWEAT('\uD83D', '\uDE13'),
PENSIVE_FACE('\uD83D', '\uDE14'),
CONFOUNDED_FACE('\uD83D', '\uDE16'),
FACE_THROWING_A_KISS('\uD83D', '\uDE18'),
KISSING_FACE_WITH_CLOSED_EYES('\uD83D', '\uDE1A'),
FACE_WITH_STUCK_OUT_TONGUE_AND_WINKING_EYE('\uD83D', '\uDE1C'),
FACE_WITH_STUCK_OUT_TONGUE_AND_TIGHTLY_CLOSED_EYES('\uD83D', '\uDE1D'),
DISAPPOINTED_FACE('\uD83D', '\uDE1E'),
ANGRY_FACE('\uD83D', '\uDE20'),
POUTING_FACE('\uD83D', '\uDE21'),
CRYING_FACE('\uD83D', '\uDE22'),
PERSEVERING_FACE('\uD83D', '\uDE23'),
FACE_WITH_LOOK_OF_TRIUMPH('\uD83D', '\uDE24'),
DISAPPOINTED_BUT_RELIEVED_FACE('\uD83D', '\uDE25'),
FEARFUL_FACE('\uD83D', '\uDE28'),
WEARY_FACE('\uD83D', '\uDE29'),
SLEEPY_FACE('\uD83D', '\uDE2A'),
TIRED_FACE('\uD83D', '\uDE2B'),
LOUDLY_CRYING_FACE('\uD83D', '\uDE2D'),
FACE_WITH_OPEN_MOUTH_AND_COLD_SWEAT('\uD83D', '\uDE30'),
FACE_SCREAMING_IN_FEAR('\uD83D', '\uDE31'),
ASTONISHED_FACE('\uD83D', '\uDE32'),
FLUSHED_FACE('\uD83D', '\uDE33'),
DIZZY_FACE('\uD83D', '\uDE35'),
FACE_WITH_MEDICAL_MASK('\uD83D', '\uDE37'),
GRINNING_CAT_FACE_WITH_SMILING_EYES('\uD83D', '\uDE38'),
CAT_FACE_WITH_TEARS_OF_JOY('\uD83D', '\uDE39'),
SMILING_CAT_FACE_WITH_OPEN_MOUTH('\uD83D', '\uDE3A'),
SMILING_CAT_FACE_WITH_HEART_SHAPED_EYES('\uD83D', '\uDE3B'),
CAT_FACE_WITH_WRY_SMILE('\uD83D', '\uDE3C'),
KISSING_CAT_FACE_WITH_CLOSED_EYES('\uD83D', '\uDE3D'),
POUTING_CAT_FACE('\uD83D', '\uDE3E'),
CRYING_CAT_FACE('\uD83D', '\uDE3F'),
WEARY_CAT_FACE('\uD83D', '\uDE40'),
FACE_WITH_NO_GOOD_GESTURE('\uD83D', '\uDE45'),
FACE_WITH_OK_GESTURE('\uD83D', '\uDE46'),
PERSON_BOWING_DEEPLY('\uD83D', '\uDE47'),
SEE_NO_EVIL_MONKEY('\uD83D', '\uDE48'),
HEAR_NO_EVIL_MONKEY('\uD83D', '\uDE49'),
SPEAK_NO_EVIL_MONKEY('\uD83D', '\uDE4A'),
HAPPY_PERSON_RAISING_ONE_HAND('\uD83D', '\uDE4B'),
PERSON_RAISING_BOTH_HANDS_IN_CELEBRATION('\uD83D', '\uDE4C'),
PERSON_FROWNING('\uD83D', '\uDE4D'),
PERSON_WITH_POUTING_FACE('\uD83D', '\uDE4E'),
PERSON_WITH_FOLDED_HANDS('\uD83D', '\uDE4F'),
// Dingbats group
BLACK_SCISSORS(null, '\u2702'),
WHITE_HEAVY_CHECK_MARK(null, '\u2705'),
AIRPLANE(null, '\u2708'),
ENVELOPE(null, '\u2709'),
RAISED_FIST(null, '\u270A'),
RAISED_HAND(null, '\u270B'),
VICTORY_HAND(null, '\u270C'),
PENCIL(null, '\u270F'),
BLACK_NIB(null, '\u2712'),
HEAVY_CHECK_MARK(null, '\u2714'),
HEAVY_MULTIPLICATION_X(null, '\u2716'),
SPARKLES(null, '\u2728'),
EIGHT_SPOKED_ASTERISK(null, '\u2733'),
EIGHT_POINTED_BLACK_STAR(null, '\u2734'),
SNOWFLAKE(null, '\u2744'),
SPARKLE(null, '\u2747'),
CROSS_MARK(null, '\u274C'),
NEGATIVE_SQUARED_CROSS_MARK(null, '\u274E'),
BLACK_QUESTION_MARK_ORNAMENT(null, '\u2753'),
WHITE_QUESTION_MARK_ORNAMENT(null, '\u2754'),
WHITE_EXCLAMATION_MARK_ORNAMENT(null, '\u2755'),
HEAVY_EXCLAMATION_MARK_SYMBOL(null, '\u2757'),
HEAVY_BLACK_HEART(null, '\u2764'),
HEAVY_PLUS_SIGN(null, '\u2795'),
HEAVY_MINUS_SIGN(null, '\u2796'),
HEAVY_DIVISION_SIGN(null, '\u2797'),
BLACK_RIGHTWARDS_ARROW(null, '\u27A1'),
CURLY_LOOP(null, '\u27B0'),
// Transport and map symbols Group
ROCKET('\uD83D', '\uDE80'),
RAILWAY_CAR('\uD83D', '\uDE83'),
HIGH_SPEED_TRAIN('\uD83D', '\uDE84'),
HIGH_SPEED_TRAIN_WITH_BULLET_NOSE('\uD83D', '\uDE85'),
METRO('\uD83D', '\uDE87'),
STATION('\uD83D', '\uDE89'),
BUS('\uD83D', '\uDE8C'),
BUS_STOP('\uD83D', '\uDE8F'),
AMBULANCE('\uD83D', '\uDE91'),
FIRE_ENGINE('\uD83D', '\uDE92'),
POLICE_CAR('\uD83D', '\uDE93'),
TAXI('\uD83D', '\uDE95'),
AUTOMOBILE('\uD83D', '\uDE97'),
RECREATIONAL_VEHICLE('\uD83D', '\uDE99'),
DELIVERY_TRUCK('\uD83D', '\uDE9A'),
SHIP('\uD83D', '\uDEA2'),
SPEEDBOAT('\uD83D', '\uDEA4'),
HORIZONTAL_TRAFFIC_LIGHT('\uD83D', '\uDEA5'),
CONSTRUCTION_SIGN('\uD83D', '\uDEA7'),
POLICE_CARS_REVOLVING_LIGHT('\uD83D', '\uDEA8'),
TRIANGULAR_FLAG_ON_POST('\uD83D', '\uDEA9'),
DOOR('\uD83D', '\uDEAA'),
NO_ENTRY_SIGN('\uD83D', '\uDEAB'),
SMOKING_SYMBOL('\uD83D', '\uDEAC'),
NO_SMOKING_SYMBOL('\uD83D', '\uDEAD'),
BICYCLE('\uD83D', '\uDEB2'),
PEDESTRIAN('\uD83D', '\uDEB6'),
MENS_SYMBOL('\uD83D', '\uDEB9'),
WOMENS_SYMBOL('\uD83D', '\uDEBA'),
RESTROOM('\uD83D', '\uDEBB'),
BABY_SYMBOL('\uD83D', '\uDEBC'),
TOILET('\uD83D', '\uDEBD'),
WATER_CLOSET('\uD83D', '\uDEBE'),
BATH('\uD83D', '\uDEC0'),
// Weather
UMBRELLA_WITH_RAIN_DROPS(null, '\u2614'),
HIGH_VOLTAGE_SIGN(null, '\u26A1'),
SNOWMAN_WITHOUT_SNOW(null, '\u26C4'),
SUN_BEHIND_CLOUD(null, '\u26C5'),
CLOSED_UMBRELLA('\uD83C', '\uDF02'),
SUN_WITH_FACE('\uD83C', '\uDF1E'),
FOGGY('\uD83C', '\uDF01'),
CLOUD(null, '\u2601'),
// Others
LEFT_RIGHT_ARROW(null, '\u2194'),
ALARM_CLOCK(null, '\u23F0'),
SOON_WITH_RIGHTWARDS_ARROW_ABOVE('\uD83D', '\uDD1C'),
EARTH_GLOBE_EUROPE_AFRICA('\uD83C', '\uDF0D'),
GLOBE_WITH_MERIDIANS('\uD83C', '\uDF10'),
STRAIGHT_RULER('\uD83D', '\uDCCF'),
INFORMATION_SOURCE(null, '\u2139'),
BLACK_RIGHT_POINTING_DOUBLE_TRIANGLE(null, '\u23E9'),
BLACK_RIGHT_POINTING_TRIANGLE(null, '\u25B6'),
BACK_WITH_LEFTWARDS_ARROW_ABOVE('\uD83D', '\uDD19'),
WRENCH('\uD83D', '\uDD27'),
DIGIT_THREE(null, '\u0033'),
CLIPBOARD('\uD83D', '\uDCCB'),
THUMBS_UP_SIGN('\uD83D', '\uDC4D'),
WHITE_RIGHT_POINTING_BACKHAND_INDEX('\uD83D', '\uDC49'),
TEAR_OFF_CALENDAR('\uD83D', '\uDCC6'),
LARGE_ORANGE_DIAMOND('\uD83D', '\uDD36'),
HUNDRED_POINTS_SYMBOL('\uD83D', '\uDCAF'),
ROUND_PUSHPIN('\uD83D', '\uDCCD');
Character firstChar;
Character secondChar;
Emoji(Character firstChar, Character secondChar) {
this.firstChar = firstChar;
this.secondChar = secondChar;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (this.firstChar != null) {
sb.append(this.firstChar);
}
if (this.secondChar != null) {
sb.append(this.secondChar);
}
return sb.toString();
}
}

207
src/main/java/org/telegram/services/LocalisationService.java

@ -0,0 +1,207 @@
package org.telegram.services;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
/**
* @author Ruben Bermudez
* @version 1.0
* @brief Localisation
* @date 25/01/15
*/
public class LocalisationService {
private static LocalisationService instance = null;
private final HashMap<String, String> supportedLanguages = new HashMap<>();
private ResourceBundle english;
private ResourceBundle spanish;
private ResourceBundle dutch;
private ResourceBundle german;
private ResourceBundle italian;
private ResourceBundle french;
private ResourceBundle malayalam;
private ResourceBundle hindi;
private ResourceBundle portuguese;
private ResourceBundle portuguesebr;
private ResourceBundle russian;
private ResourceBundle arabic;
private ResourceBundle catalan;
private ResourceBundle galician;
private ResourceBundle persian;
private ResourceBundle turkish;
private class CustomClassLoader extends ClassLoader {
public CustomClassLoader(ClassLoader parent) {
super(parent);
}
public InputStream getResourceAsStream(String name) {
InputStream utf8in = getParent().getResourceAsStream(name);
if (utf8in != null) {
try {
byte[] utf8Bytes = new byte[utf8in.available()];
utf8in.read(utf8Bytes, 0, utf8Bytes.length);
byte[] iso8859Bytes = new String(utf8Bytes, "UTF-8").getBytes("ISO-8859-1");
return new ByteArrayInputStream(iso8859Bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
utf8in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
/**
* Singleton
*
* @return Instance of localisation service
*/
public static LocalisationService getInstance() {
if (instance == null) {
synchronized (LocalisationService.class) {
if (instance == null) {
instance = new LocalisationService();
}
}
}
return instance;
}
/**
* Private constructor due to singleton
*/
private LocalisationService() {
CustomClassLoader loader = new CustomClassLoader(Thread.currentThread().getContextClassLoader());
english = ResourceBundle.getBundle("localisation.strings", new Locale("en", "US"), loader);
supportedLanguages.put("en", "English");
spanish = ResourceBundle.getBundle("localisation.strings", new Locale("es", "ES"), loader);
supportedLanguages.put("es", "Español");
portuguese = ResourceBundle.getBundle("localisation.strings", new Locale("pt", "PT"), loader);
supportedLanguages.put("pt", "Português");
dutch = ResourceBundle.getBundle("localisation.strings", new Locale("nl", "NL"), loader);
supportedLanguages.put("nl", "Nederlands");
/*
german = ResourceBundle.getBundle("localisation.strings", new Locale("de", "DE"), loader);
supportedLanguages.put("de", "Deutsch");
italian = ResourceBundle.getBundle("localisation.strings", new Locale("it", "IT"), loader);
supportedLanguages.put("it", "Italian");
french = ResourceBundle.getBundle("localisation.strings", new Locale("fr", "FR"), loader);
supportedLanguages.put("fr", "French");
portuguesebr = ResourceBundle.getBundle("localisation.strings", new Locale("pt", "BR"), loader);
supportedLanguages.put("pt_br", "Portuguese BR");*/
/**
malayalam = ResourceBundle.getBundle("localisation.strings", new Locale("ml", "ML"), loader);
hindi = ResourceBundle.getBundle("localisation.strings", new Locale("hi", "HI"), loader);
russian = ResourceBundle.getBundle("localisation.strings", new Locale("ru", "RU"), loader);
arabic = ResourceBundle.getBundle("localisation.strings", new Locale("ar", "AR"), loader);
catalan = ResourceBundle.getBundle("localisation.strings", new Locale("ca", "CA"), loader);
galician = ResourceBundle.getBundle("localisation.strings", new Locale("gl", "ES"), loader);
persian = ResourceBundle.getBundle("localisation.strings", new Locale("fa", "FA"), loader);
turkish = ResourceBundle.getBundle("localisation.strings", new Locale("tr", "TR"), loader);
*/
}
/**
* Get a string in default language (en)
*
* @param key key of the resource to fetch
* @return fetched string or error message otherwise
*/
public String getString(String key) {
String result;
try {
result = english.getString(key);
} catch (MissingResourceException e) {
result = "String not found";
}
return result;
}
/**
* Get a string in default language
*
* @param key key of the resource to fetch
* @return fetched string or error message otherwise
*/
public String getString(String key, String language) {
String result;
try {
switch (language.toLowerCase()) {
case "en":
result = english.getString(key);
break;
case "es":
result = spanish.getString(key);
break;
case "pt":
result = portuguese.getString(key);
break;
case "nl":
result = dutch.getString(key);
break;
/*case "de":
result = german.getString(key);
break;
case "it":
result = italian.getString(key);
break;
case "fr":
result = french.getString(key);
break;
case "ml":
result = malayalam.getString(key);
break;
case "hi":
result = hindi.getString(key);
break;
case "pt-BR":
result = portuguesebr.getString(key);
break;
case "ru":
result = russian.getString(key);
break;
case "ar":
result = arabic.getString(key);
break;
case "ca":
result = catalan.getString(key);
break;
case "gl":
result = galician.getString(key);
break;
case "fa":
result = persian.getString(key);
break;
case "tr":
result = turkish.getString(key);
break;*/
default:
result = english.getString(key);
break;
}
} catch (MissingResourceException e) {
result = english.getString(key);
}
return result;
}
public HashMap<String, String> getSupportedLanguages() {
return supportedLanguages;
}
public String getLanguageCodeByName(String language) {
return supportedLanguages.entrySet().stream().filter(x -> x.getValue().equals(language)).findFirst().get().getKey();
}
}

108
src/main/java/org/telegram/services/TimerExecutor.java

@ -0,0 +1,108 @@
package org.telegram.services;
import java.time.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author Ruben Bermudez
* @version 2.0
* @brief Exectue a task periodically
* @date 27/01/25
*/
public class TimerExecutor {
private static volatile BotLogger log = BotLogger.getLogger(TimerExecutor.class.getName());
private static volatile TimerExecutor instance; ///< Instance
private static final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); ///< Thread to execute operations
/**
* Private constructor due to singleton
*/
private TimerExecutor() {
}
/**
* Singleton pattern
*
* @return Instance of the executor
*/
public static TimerExecutor getInstance() {
final TimerExecutor currentInstance;
if (instance == null) {
synchronized (TimerExecutor.class) {
if (instance == null) {
instance = new TimerExecutor();
}
currentInstance = instance;
}
} else {
currentInstance = instance;
}
return currentInstance;
}
/**
* Add a new CustomTimerTask to be executed
*
* @param task Task to execute
* @param targetHour Hour to execute it
* @param targetMin Minute to execute it
* @param targetSec Second to execute it
*/
public void startExecutionEveryDayAt(CustomTimerTask task, int targetHour, int targetMin, int targetSec) {
log.warn("Posting new task" + task.getTaskName());
final Runnable taskWrapper = () -> {
try {
task.execute();
task.reduceTimes();
startExecutionEveryDayAt(task, targetHour, targetMin, targetSec);
} catch (Exception e) {
log.severe("Bot threw an unexpected exception at TimerExecutor", e);
}
};
if (task.getTimes() != 0) {
final long delay = computNextDilay(targetHour, targetMin, targetSec);
executorService.schedule(taskWrapper, delay, TimeUnit.SECONDS);
}
}
/**
* Find out next daily execution
*
* @param targetHour Target hour
* @param targetMin Target minute
* @param targetSec Target second
* @return time in second to wait
*/
private long computNextDilay(int targetHour, int targetMin, int targetSec) {
final LocalDateTime localNow = LocalDateTime.now(Clock.systemUTC());
LocalDateTime localNextTarget = localNow.withHour(targetHour).withMinute(targetMin).withSecond(targetSec);
while (localNow.compareTo(localNextTarget) > 0) {
localNextTarget = localNextTarget.plusDays(1);
}
final Duration duration = Duration.between(localNow, localNextTarget);
return duration.getSeconds();
}
@Override
public void finalize() {
this.stop();
}
/**
* Stop the thread
*/
public void stop() {
executorService.shutdown();
try {
executorService.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException ex) {
log.severe(ex);
} catch (Exception e) {
log.severe("Bot threw an unexpected exception at TimerExecutor", e);
}
}
}

241
src/main/java/org/telegram/services/TransifexService.java

@ -19,6 +19,8 @@ import java.io.*;
* @date 21 of June of 2015
*/
public class TransifexService {
private static volatile BotLogger log = BotLogger.getLogger(TransifexService.class.getName());
private static final String BASEURLAndroid = "http://" + BuildVars.TRANSIFEXUSER + ":" + BuildVars.TRANSIFEXPASSWORD + "@www.transifex.com/api/2/project/telegram/resource/stringsxml-48/translation/@language?file"; ///< Base url for REST
private static final String BASEURLiOS = "http://" + BuildVars.TRANSIFEXUSER + ":" + BuildVars.TRANSIFEXPASSWORD + "@www.transifex.com/api/2/project/iphone-1/resource/localizablestrings/translation/@language?file"; ///< Base url for REST
private static final String BASEURLOSX = "http://" + BuildVars.TRANSIFEXUSER + ":" + BuildVars.TRANSIFEXPASSWORD + "@www.transifex.com/api/2/project/osx/resource/localizablestrings/translation/@language?file"; ///< Base url for REST
@ -74,7 +76,7 @@ public class TransifexService {
result = responseString;
}
} catch (IOException e) {
e.printStackTrace();
log.error(e);
}
return result;
}
@ -87,7 +89,7 @@ public class TransifexService {
HttpResponse response = client.execute(request);
result = IOUtils.toByteArray(new InputStreamReader(response.getEntity().getContent(), "UTF-16LE"));
} catch (IOException e) {
e.printStackTrace();
log.error(e);
}
return result;
}
@ -100,7 +102,7 @@ public class TransifexService {
HttpResponse response = client.execute(request);
result = IOUtils.toByteArray(new InputStreamReader(response.getEntity().getContent(), "UTF-16LE"));
} catch (IOException e) {
e.printStackTrace();
log.error(e);
}
return result;
}
@ -113,7 +115,7 @@ public class TransifexService {
HttpResponse response = client.execute(request);
result = IOUtils.toByteArray(new InputStreamReader(response.getEntity().getContent(), "UTF-16LE"));
} catch (IOException e) {
e.printStackTrace();
log.error(e);
}
return result;
}
@ -126,7 +128,7 @@ public class TransifexService {
HttpResponse response = client.execute(request);
result = IOUtils.toByteArray(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
} catch (IOException e) {
e.printStackTrace();
log.error(e);
}
return result;
}
@ -139,7 +141,7 @@ public class TransifexService {
HttpResponse response = client.execute(request);
result = IOUtils.toByteArray(new InputStreamReader(response.getEntity().getContent(), "UTF-16LE"));
} catch (IOException e) {
e.printStackTrace();
log.error(e);
}
return result;
}
@ -152,7 +154,7 @@ public class TransifexService {
HttpResponse response = client.execute(request);
result = IOUtils.toByteArray(new InputStreamReader(response.getEntity().getContent(), "UTF-16LE"));
} catch (IOException e) {
e.printStackTrace();
log.error(e);
}
return result;
}
@ -177,24 +179,26 @@ public class TransifexService {
* @param language Language requested
*/
public SendDocument getAndroidSupportLanguageFile(String language) {
String file = getFileAndroid(language);
SendDocument sendDocument;
if (file != null && file.getBytes().length / BYTES1024 >= 10) {
file = file.replaceAll("\"LanguageName\"\\>(\\w*)\\<\\/string\\>", "\"LanguageName\"\\>$1_1\\<\\/string\\>").replaceAll("\"LanguageCode\"\\>(\\w*)\\<\\/string\\>", "\"LanguageCode\"\\>$1_1\\<\\/string\\>");
try {
String fileName = "languages_Android_" + language + ".xml";
PrintWriter localFile = new PrintWriter(fileName);
localFile.print(file);
localFile.close();
File fileToUpload = new File(fileName);
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
sendDocument = null;
SendDocument sendDocument = null;
try {
String file = getFileAndroid(language);
if (file != null && file.getBytes().length / BYTES1024 >= 10) {
file = file.replaceAll("\"LanguageName\"\\>(\\w*)\\<\\/string\\>", "\"LanguageName\"\\>$1_1\\<\\/string\\>").replaceAll("\"LanguageCode\"\\>(\\w*)\\<\\/string\\>", "\"LanguageCode\"\\>$1_1\\<\\/string\\>");
try {
String fileName = "languages_Android_" + language + ".xml";
PrintWriter localFile = new PrintWriter(fileName);
localFile.print(file);
localFile.close();
File fileToUpload = new File(fileName);
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
} catch (FileNotFoundException e) {
log.error(e);
}
}
} else {
sendDocument = null;
} catch (Exception e) {
log.error(e);
}
return sendDocument;
}
@ -204,23 +208,24 @@ public class TransifexService {
* @param language Language requested
*/
public SendDocument getAndroidLanguageFile(String language) {
String file = getFileAndroid(language);
SendDocument sendDocument;
if (file != null && file.getBytes().length / BYTES1024 >= 10) {
try {
String fileName = "languages_Android_" + language + ".xml";
PrintWriter localFile = new PrintWriter(fileName);
localFile.print(file);
localFile.close();
File fileToUpload = new File(fileName);
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
sendDocument = null;
SendDocument sendDocument = null;
try {
String file = getFileAndroid(language);
if (file != null && file.getBytes().length / BYTES1024 >= 10) {
try {
String fileName = "languages_Android_" + language + ".xml";
PrintWriter localFile = new PrintWriter(fileName);
localFile.print(file);
localFile.close();
File fileToUpload = new File(fileName);
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
} catch (FileNotFoundException e) {
log.error(e);
}
}
} else {
sendDocument = null;
} catch (Exception e) {
e.printStackTrace();
}
return sendDocument;
}
@ -231,23 +236,24 @@ public class TransifexService {
* @param language Language requested
*/
public SendDocument getiOSLanguageFile(String language) {
byte[] file = getFileiOS(language);
SendDocument sendDocument;
if (file != null && file.length / BYTES1024 >= 10) {
try {
String fileName = "languages_ios_" + language + ".strings";
File fileToUpload = new File(fileName);
FileOutputStream output = new FileOutputStream(fileToUpload);
IOUtils.write(file, output);
output.close();
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
} catch (IOException e) {
e.printStackTrace();
sendDocument = null;
SendDocument sendDocument = null;
try {
byte[] file = getFileiOS(language);
if (file != null && file.length / BYTES1024 >= 10) {
try {
String fileName = "languages_ios_" + language + ".strings";
File fileToUpload = new File(fileName);
FileOutputStream output = new FileOutputStream(fileToUpload);
IOUtils.write(file, output);
output.close();
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
sendDocument = null;
} catch (Exception e) {
e.printStackTrace();
}
return sendDocument;
}
@ -257,23 +263,24 @@ public class TransifexService {
* @param language Language requested
*/
public SendDocument getOSXLanguageFile(String language) {
byte[] file = getFileOSX(language);
SendDocument sendDocument;
if (file != null && file.length / BYTES1024 >= 10) {
try {
String fileName = "languages_osx_" + language + ".strings";
File fileToUpload = new File(fileName);
FileOutputStream output = new FileOutputStream(fileToUpload);
IOUtils.write(file, output);
output.close();
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
} catch (IOException e) {
e.printStackTrace();
sendDocument = null;
SendDocument sendDocument = null;
try {
byte[] file = getFileOSX(language);
if (file != null && file.length / BYTES1024 >= 10) {
try {
String fileName = "languages_osx_" + language + ".strings";
File fileToUpload = new File(fileName);
FileOutputStream output = new FileOutputStream(fileToUpload);
IOUtils.write(file, output);
output.close();
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
sendDocument = null;
} catch (Exception e) {
e.printStackTrace();
}
return sendDocument;
}
@ -283,22 +290,26 @@ public class TransifexService {
* @param language Language requested
*/
public SendDocument getTdesktopLanguageFile(String language) {
byte[] file = getFileTDesktop(language);
SendDocument sendDocument = null;
if (file != null && file.length / BYTES1024 >= 10) {
try {
String fileName = "languages_tdesktop_" + language + ".strings";
File fileToUpload = new File(fileName);
FileOutputStream output = new FileOutputStream(fileToUpload);
IOUtils.write(file, output);
output.close();
if (fileToUpload.exists()) {
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
try {
byte[] file = getFileTDesktop(language);
if (file != null && file.length / BYTES1024 >= 10) {
try {
String fileName = "languages_tdesktop_" + language + ".strings";
File fileToUpload = new File(fileName);
FileOutputStream output = new FileOutputStream(fileToUpload);
IOUtils.write(file, output);
output.close();
if (fileToUpload.exists()) {
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
return sendDocument;
}
@ -308,22 +319,26 @@ public class TransifexService {
* @param language Language requested
*/
public SendDocument getWebogramLanguageFile(String language) {
byte[] file = getFileWebogram(language);
SendDocument sendDocument = null;
if (file != null && file.length / BYTES1024 >= 10) {
try {
String fileName = "languages_webogram_" + language + ".json";
File fileToUpload = new File(fileName);
FileOutputStream output = new FileOutputStream(fileToUpload);
IOUtils.write(file, output);
output.close();
if (fileToUpload.exists()) {
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
try {
byte[] file = getFileWebogram(language);
if (file != null && file.length / BYTES1024 >= 10) {
try {
String fileName = "languages_webogram_" + language + ".json";
File fileToUpload = new File(fileName);
FileOutputStream output = new FileOutputStream(fileToUpload);
IOUtils.write(file, output);
output.close();
if (fileToUpload.exists()) {
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
return sendDocument;
}
@ -333,22 +348,26 @@ public class TransifexService {
* @param language Language requested
*/
public SendDocument getWPLanguageFile(String language) {
byte[] file = getFileWP(language);
SendDocument sendDocument = null;
if (file != null && file.length / BYTES1024 >= 10) {
try {
String fileName = "languages_wp_" + language + ".xml";
File fileToUpload = new File(fileName);
FileOutputStream output = new FileOutputStream(fileToUpload);
IOUtils.write(file, output);
output.close();
if (fileToUpload.exists()) {
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
try {
byte[] file = getFileWP(language);
if (file != null && file.length / BYTES1024 >= 10) {
try {
String fileName = "languages_wp_" + language + ".xml";
File fileToUpload = new File(fileName);
FileOutputStream output = new FileOutputStream(fileToUpload);
IOUtils.write(file, output);
output.close();
if (fileToUpload.exists()) {
sendDocument = new SendDocument();
sendDocument.setNewDocument(fileToUpload.getAbsolutePath(), fileName);
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
return sendDocument;
}

294
src/main/java/org/telegram/services/WeatherService.java

@ -1,17 +1,17 @@
package org.telegram.services;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.telegram.BuildVars;
import org.telegram.database.DatabaseManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.Instant;
@ -26,12 +26,18 @@ import java.time.format.DateTimeFormatter;
* @date 20 of June of 2015
*/
public class WeatherService {
private static volatile BotLogger log = BotLogger.getLogger(WeatherService.class.getName());
public static final String METRICSYSTEM = "metric";
public static final String IMPERIALSYSTEM = "imperial";
private static final String BASEURL = "http://api.openweathermap.org/data/2.5/"; ///< Base url for REST
private static final String FORECASTPATH = "forecast/daily";
private static final String CURRENTPATH = "weather";
private static final String APIIDEND = "&APPID=" + BuildVars.OPENWEATHERAPIKEY;
private static final String FORECASTPARAMS = "&cnt=3&units=metric";
private static final String CURRENTPARAMS = "&cnt=1&units=metric";
private static final String FORECASTPARAMS = "&cnt=3&units=@units@&lang=@language@";
private static final String ALERTPARAMS = "&cnt=1&units=@units@&lang=@language@";
private static final String CURRENTPARAMS = "&cnt=1&units=@units@&lang=@language@";
private static final DateTimeFormatter dateFormaterFromDate = DateTimeFormatter.ofPattern("dd/MM/yyyy"); ///< Date to text formater
private static volatile WeatherService instance; ///< Instance of this class
@ -61,6 +67,47 @@ public class WeatherService {
return currentInstance;
}
/**
* Fetch the weather of a city for one day
*
* @param cityId City to get the weather
* @return userHash to be send to use
* @note Forecast for the day
*/
public String fetchWeatherAlert(int cityId, int userId, String language, String units) {
String cityFound;
String responseToUser;
try {
String completURL = BASEURL + FORECASTPATH + "?" + getCityQuery(cityId + "") +
ALERTPARAMS.replace("@language@", language).replace("@units@", units) + APIIDEND;
CloseableHttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
HttpGet request = new HttpGet(completURL);
CloseableHttpResponse response = client.execute(request);
HttpEntity ht = response.getEntity();
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
String responseString = EntityUtils.toString(buf, "UTF-8");
JSONObject jsonObject = new JSONObject(responseString);
log.warning(jsonObject.toString());
if (jsonObject.getInt("cod") == 200) {
cityFound = jsonObject.getJSONObject("city").getString("name") + " (" +
jsonObject.getJSONObject("city").getString("country") + ")";
saveRecentWeather(userId, cityFound, jsonObject.getJSONObject("city").getInt("id"));
responseToUser = String.format(LocalisationService.getInstance().getString("weatherAlert", language),
cityFound, convertListOfForecastToString(jsonObject, language, units, false));
} else {
log.warning(jsonObject.toString());
responseToUser = LocalisationService.getInstance().getString("cityNotFound", language);
}
} catch (Exception e) {
log.error(e);
responseToUser = LocalisationService.getInstance().getString("errorFetchingWeather", language);
}
return responseToUser;
}
/**
* Fetch the weather of a city
*
@ -68,35 +115,36 @@ public class WeatherService {
* @return userHash to be send to use
* @note Forecast for the following 3 days
*/
public String fetchWeatherForecast(String city, Integer userId) {
public String fetchWeatherForecast(String city, Integer userId, String language, String units) {
String cityFound;
String responseToUser;
try {
String completURL = BASEURL + FORECASTPATH + "?" + getCityQuery(city) + FORECASTPARAMS + APIIDEND;
HttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
String completURL = BASEURL + FORECASTPATH + "?" + getCityQuery(city) +
FORECASTPARAMS.replace("@language@", language).replace("@units@", units) + APIIDEND;
CloseableHttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
HttpGet request = new HttpGet(completURL);
HttpResponse response = client.execute(request);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line;
String responseString = "";
while ((line = rd.readLine()) != null) {
responseString += line;
}
CloseableHttpResponse response = client.execute(request);
HttpEntity ht = response.getEntity();
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
String responseString = EntityUtils.toString(buf, "UTF-8");
JSONObject jsonObject = new JSONObject(responseString);
log.warning(jsonObject.toString());
if (jsonObject.getInt("cod") == 200) {
cityFound = jsonObject.getJSONObject("city").getString("name") + " (" +
jsonObject.getJSONObject("city").getString("country") + ")";
saveRecentWeather(userId, cityFound, jsonObject.getJSONObject("city").getInt("id"));
responseToUser = "The weather for " + cityFound + " will be:\n\n";
responseToUser += convertListOfForecastToString(jsonObject);
responseToUser += "Thank you for using our Weather Bot.\n\n" +
"Your Telegram Team";
responseToUser = String.format(LocalisationService.getInstance().getString("weatherForcast", language),
cityFound, convertListOfForecastToString(jsonObject, language, units, true));
} else {
responseToUser = "City not found";
log.warning(jsonObject.toString());
responseToUser = LocalisationService.getInstance().getString("cityNotFound", language);
}
} catch (IOException e) {
responseToUser = "Error fetching weather info";
} catch (Exception e) {
log.error(e);
responseToUser = LocalisationService.getInstance().getString("errorFetchingWeather", language);
}
return responseToUser;
}
@ -107,35 +155,35 @@ public class WeatherService {
* @return userHash to be send to use
* @note Forecast for the following 3 days
*/
public String fetchWeatherForecastByLocation(Double longitude, Double latitude, Integer userId) {
public String fetchWeatherForecastByLocation(Double longitude, Double latitude, Integer userId, String language, String units) {
String cityFound;
String responseToUser;
try {
String completURL = BASEURL + FORECASTPATH + "?lat=" + URLEncoder.encode(latitude + "", "UTF-8") + "&lon=" + URLEncoder.encode(longitude + "", "UTF-8") + FORECASTPARAMS + APIIDEND;;
HttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
String completURL = BASEURL + FORECASTPATH + "?lat=" + URLEncoder.encode(latitude + "", "UTF-8") + "&lon="
+ URLEncoder.encode(longitude + "", "UTF-8") +
FORECASTPARAMS.replace("@language@", language).replace("@units@", units) + APIIDEND;;
CloseableHttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
HttpGet request = new HttpGet(completURL);
HttpResponse response = client.execute(request);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line;
String responseString = "";
while ((line = rd.readLine()) != null) {
responseString += line;
}
CloseableHttpResponse response = client.execute(request);
HttpEntity ht = response.getEntity();
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
String responseString = EntityUtils.toString(buf, "UTF-8");
JSONObject jsonObject = new JSONObject(responseString);
if (jsonObject.getInt("cod") == 200) {
cityFound = jsonObject.getJSONObject("city").getString("name") + " (" +
jsonObject.getJSONObject("city").getString("country") + ")";
saveRecentWeather(userId, cityFound, jsonObject.getJSONObject("city").getInt("id"));
responseToUser = "The weather for " + cityFound + " will be:\n\n";
responseToUser += convertListOfForecastToString(jsonObject);
responseToUser += "Thank you for using our Weather Bot.\n\n" +
"Your Telegram Team";
responseToUser = String.format(LocalisationService.getInstance().getString("weatherForcast", language),
cityFound, convertListOfForecastToString(jsonObject, language, units, true));
} else {
responseToUser = "City not found";
log.warning(jsonObject.toString());
responseToUser = LocalisationService.getInstance().getString("cityNotFound", language);
}
} catch (IOException e) {
responseToUser = "Error fetching weather info";
} catch (Exception e) {
log.error(e);
responseToUser = LocalisationService.getInstance().getString("errorFetchingWeather", language);
}
return responseToUser;
}
@ -147,35 +195,36 @@ public class WeatherService {
* @return userHash to be send to use
* @note Forecast for the following 3 days
*/
public String fetchWeatherCurrent(String city, Integer userId) {
public String fetchWeatherCurrent(String city, Integer userId, String language, String units) {
String cityFound;
String responseToUser;
Emoji emoji = null;
try {
String completURL = BASEURL + CURRENTPATH + "?" + getCityQuery(city) + CURRENTPARAMS + APIIDEND;
HttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
String completURL = BASEURL + CURRENTPATH + "?" + getCityQuery(city) +
CURRENTPARAMS.replace("@language@", language).replace("@units@", units) + APIIDEND;
CloseableHttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
HttpGet request = new HttpGet(completURL);
HttpResponse response = client.execute(request);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line;
String responseString = "";
while ((line = rd.readLine()) != null) {
responseString += line;
}
CloseableHttpResponse response = client.execute(request);
HttpEntity ht = response.getEntity();
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
String responseString = EntityUtils.toString(buf, "UTF-8");
JSONObject jsonObject = new JSONObject(responseString);
if (jsonObject.getInt("cod") == 200) {
cityFound = jsonObject.getString("name") + " (" +
jsonObject.getJSONObject("sys").getString("country") + ")";
saveRecentWeather(userId, cityFound, jsonObject.getInt("id"));
responseToUser = "The weather for " + cityFound + " is:\n\n";
responseToUser += convertCurrentWeatherToString(jsonObject);
responseToUser += "Thank you for using our Weather Bot.\n\n" +
"Your Telegram Team";
emoji = getEmojiForWeather(jsonObject.getJSONArray("weather").getJSONObject(0));
responseToUser = String.format(LocalisationService.getInstance().getString("weatherCurrent", language),
cityFound, convertCurrentWeatherToString(jsonObject, language, units, emoji));
} else {
responseToUser = "City not found";
log.warning(jsonObject.toString());
responseToUser = LocalisationService.getInstance().getString("cityNotFound", language);
}
} catch (IOException e) {
responseToUser = "Error fetching weather info";
} catch (Exception e) {
log.error(e);
responseToUser = LocalisationService.getInstance().getString("errorFetchingWeather", language);
}
return responseToUser;
}
@ -186,49 +235,51 @@ public class WeatherService {
* @return userHash to be send to use
* @note Forecast for the following 3 days
*/
public String fetchWeatherCurrentByLocation(Double longitude, Double latitude, Integer userId) {
public String fetchWeatherCurrentByLocation(Double longitude, Double latitude, Integer userId, String language, String units) {
String cityFound;
String responseToUser;
try {
String completURL = BASEURL + CURRENTPATH + "?q=" + URLEncoder.encode("lat=" + latitude + "&lon=" + longitude, "UTF-8") + CURRENTPARAMS + APIIDEND;;
HttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
String completURL = BASEURL + CURRENTPATH + "?lat=" + URLEncoder.encode(latitude + "", "UTF-8") + "&lon="
+ URLEncoder.encode(longitude + "", "UTF-8") +
CURRENTPARAMS.replace("@language@", language).replace("@units@", units) + APIIDEND;;
CloseableHttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
HttpGet request = new HttpGet(completURL);
HttpResponse response = client.execute(request);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line;
String responseString = "";
while ((line = rd.readLine()) != null) {
responseString += line;
}
CloseableHttpResponse response = client.execute(request);
HttpEntity ht = response.getEntity();
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
String responseString = EntityUtils.toString(buf, "UTF-8");
JSONObject jsonObject = new JSONObject(responseString);
if (jsonObject.getInt("cod") == 200) {
cityFound = jsonObject.getString("name") + " (" +
jsonObject.getJSONObject("sys").getString("country") + ")";
saveRecentWeather(userId, cityFound, jsonObject.getInt("id"));
responseToUser = "The weather for " + cityFound + " is:\n\n";
responseToUser += convertCurrentWeatherToString(jsonObject);
responseToUser += "Thank you for using our Weather Bot.\n\n" +
"Your Telegram Team";
responseToUser = String.format(LocalisationService.getInstance().getString("weatherCurrent", language),
cityFound, convertCurrentWeatherToString(jsonObject, language, units, null));
} else {
responseToUser = "City not found";
log.warning(jsonObject.toString());
responseToUser = LocalisationService.getInstance().getString("cityNotFound", language);
}
} catch (IOException e) {
responseToUser = "Error fetching weather info";
} catch (Exception e) {
log.error(e);
responseToUser = LocalisationService.getInstance().getString("errorFetchingWeather", language);
}
return responseToUser;
}
private String convertCurrentWeatherToString(JSONObject jsonObject) {
String temp = jsonObject.getJSONObject("main").getDouble("temp")+"";
private String convertCurrentWeatherToString(JSONObject jsonObject, String language, String units, Emoji emoji) {
String temp = ((int)jsonObject.getJSONObject("main").getDouble("temp"))+"";
String cloudiness = jsonObject.getJSONObject("clouds").getInt("all") + "%";
String weatherDesc = jsonObject.getJSONArray("weather").getJSONObject(0).getString("description");
String responseToUser = "";
responseToUser +=
" |-- Weather: " + weatherDesc + "\n" +
" |-- Cloudiness: " + cloudiness + "\n" +
" |-- Temperature: " + temp + "ºC\n\n";
String responseToUser;
if (units.equals(METRICSYSTEM)) {
responseToUser = LocalisationService.getInstance().getString("currentWeatherPartMetric", language);
} else {
responseToUser = LocalisationService.getInstance().getString("currentWeatherPartImperial", language);
}
responseToUser = String.format(responseToUser, emoji == null ? weatherDesc : emoji.toString(), cloudiness, temp);
return responseToUser;
}
@ -239,11 +290,11 @@ public class WeatherService {
* @param jsonObject JSONObject contining the list
* @return String to be sent to the user
*/
private String convertListOfForecastToString(JSONObject jsonObject) {
private String convertListOfForecastToString(JSONObject jsonObject, String language, String units, boolean addDate) {
String responseToUser = "";
for (int i = 0; i < jsonObject.getJSONArray("list").length(); i++) {
JSONObject internalJSON = jsonObject.getJSONArray("list").getJSONObject(i);
responseToUser += convertInternalInformationToString(internalJSON);
responseToUser += convertInternalInformationToString(internalJSON, language, units, addDate);
}
return responseToUser;
}
@ -254,22 +305,40 @@ public class WeatherService {
* @param internalJSON JSONObject containing the part to convert
* @return String to be sent to the user
*/
private String convertInternalInformationToString(JSONObject internalJSON) {
private String convertInternalInformationToString(JSONObject internalJSON, String language, String units, boolean addDate) {
String responseToUser = "";
LocalDate date;
String tempMax;
String tempMin;
String weatherDesc;
date = Instant.ofEpochSecond(internalJSON.getLong("dt")).atZone(ZoneId.systemDefault()).toLocalDate();
tempMax = internalJSON.getJSONObject("temp").getDouble("max") + "";
tempMin = internalJSON.getJSONObject("temp").getDouble("min") + "";
tempMax = ((int)internalJSON.getJSONObject("temp").getDouble("max")) + "";
tempMin = ((int)internalJSON.getJSONObject("temp").getDouble("min")) + "";
JSONObject weatherObject = internalJSON.getJSONArray("weather").getJSONObject(0);
Emoji emoji = getEmojiForWeather(internalJSON.getJSONArray("weather").getJSONObject(0));
weatherDesc = weatherObject.getString("description");
responseToUser += "*On " + dateFormaterFromDate.format(date) + "\n" +
" |--Forecast: " + weatherDesc + "\n" +
" |--High temperature: " + tempMax + "ºC\n" +
" |--Low temperature: " + tempMin + "ºC\n\n";
if (units.equals(METRICSYSTEM)) {
if (addDate) {
responseToUser = LocalisationService.getInstance().getString("forecastWeatherPartMetric", language);
} else {
responseToUser = LocalisationService.getInstance().getString("alertWeatherPartMetric", language);
}
} else {
if (addDate) {
responseToUser = LocalisationService.getInstance().getString("forecastWeatherPartImperial", language);
} else {
responseToUser = LocalisationService.getInstance().getString("alertWeatherPartImperial", language);
}
}
if (addDate) {
responseToUser = String.format(responseToUser, Emoji.LARGE_ORANGE_DIAMOND.toString(),
dateFormaterFromDate.format(date), emoji == null ? weatherDesc : emoji.toString(), tempMax, tempMin);
} else {
responseToUser = String.format(responseToUser, emoji == null ? weatherDesc : emoji.toString(),
tempMax, tempMin);
}
return responseToUser;
}
@ -286,4 +355,47 @@ public class WeatherService {
}
return cityQuery;
}
private Emoji getEmojiForWeather(JSONObject weather) {
Emoji emoji;
switch(weather.getString("icon")) {
case "01n":
case "01d":
emoji = Emoji.SUN_WITH_FACE;
break;
case "02n":
case "02d":
emoji = Emoji.SUN_BEHIND_CLOUD;
break;
case "03n":
case "03d":
case "04n":
case "04d":
emoji = Emoji.CLOUD;
break;
case "09n":
case "09d":
case "10n":
case "10d":
emoji = Emoji.UMBRELLA_WITH_RAIN_DROPS;
break;
case "11n":
case "11d":
emoji = Emoji.HIGH_VOLTAGE_SIGN;
break;
case "13n":
case "13d":
emoji = Emoji.SNOWFLAKE;
break;
case "50n":
case "50d":
emoji = Emoji.FOGGY;
break;
default:
emoji = null;
}
return emoji;
}
}

40
src/main/java/org/telegram/structure/WeatherAlert.java

@ -0,0 +1,40 @@
package org.telegram.structure;
/**
* @author Ruben Bermudez
* @version 1.0
* @brief Weather Alert representation
* @date 23 of July of 2015
*/
public class WeatherAlert {
private int id;
private int userId;
private int cityId;
public WeatherAlert() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getCityId() {
return cityId;
}
public void setCityId(int cityId) {
this.cityId = cityId;
}
}

215
src/main/java/org/telegram/updateshandlers/DirectionsHandlers.java

@ -1,17 +1,19 @@
package org.telegram.updateshandlers;
import org.telegram.*;
import org.telegram.api.ForceReply;
import org.telegram.api.Message;
import org.telegram.api.ReplyKeyboardHide;
import org.telegram.api.Update;
import org.telegram.api.*;
import org.telegram.database.DatabaseManager;
import org.telegram.methods.SendMessage;
import org.telegram.services.DirectionsService;
import org.telegram.services.LocalisationService;
import org.telegram.updatesreceivers.UpdatesThread;
import org.telegram.updatesreceivers.Webhook;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* @author Ruben Bermudez
@ -21,15 +23,16 @@ import java.util.List;
*/
public class DirectionsHandlers implements UpdatesCallback {
private static final String TOKEN = BotConfig.TOKENDIRECTIONS;
private final int webhookPort = 9993;
private static final String webhookPath = "directionsBot";
private final Webhook webhook;
private final UpdatesThread updatesThread;
private static final int WATING_ORIGIN_STATUS = 0;
private static final int WATING_DESTINY_STATUS = 1;
private final ConcurrentLinkedQueue<Integer> languageMessages = new ConcurrentLinkedQueue<>();
public DirectionsHandlers() {
if (BuildVars.useWebHook) {
webhook = new Webhook(this, webhookPort);
webhook = new Webhook(this, webhookPath);
updatesThread = null;
SenderHelper.SendWebhook(webhook.getURL(), TOKEN);
} else {
@ -44,83 +47,143 @@ public class DirectionsHandlers implements UpdatesCallback {
handleDirections(update);
}
@Override
public void onUpdatesReceived(List<Update> updates) {
for (Update update: updates) {
handleDirections(update);
}
}
public void handleDirections(Update update) {
Message message = update.getMessage();
if (message != null && message.hasText()) {
if (message.getText().startsWith(Commands.startDirectionCommand)) {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setChatId(message.getChatId());
sendMessageRequest.setReplayToMessageId(message.getMessageId());
ForceReply forceReply = new ForceReply();
forceReply.setSelective(true);
sendMessageRequest.setReplayMarkup(forceReply);
sendMessageRequest.setText(CustomMessages.initDirections);
Message sentMessage = SenderHelper.SendMessage(sendMessageRequest, TOKEN);
if (sentMessage != null) {
DatabaseManager.getInstance().addUserForDirection(message.getFrom().getId(), WATING_ORIGIN_STATUS,
sentMessage.getMessageId(),null);
}
} else if (message.getText().startsWith(Commands.help) ||
(message.getText().startsWith(Commands.startCommand) || !message.isGroupMessage())) {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(CustomMessages.helpDirections);
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
} else if (!message.getText().startsWith("/")){
if (DatabaseManager.getInstance().getUserDestinationStatus(message.getFrom().getId()) == WATING_ORIGIN_STATUS &&
message.hasReplayMessage() &&
DatabaseManager.getInstance().getUserDestinationMessageId(message.getFrom().getId()) == message.getReplyToMessage().getMessageId()) {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setChatId(message.getChatId());
sendMessageRequest.setReplayToMessageId(message.getMessageId());
ForceReply forceReply = new ForceReply();
forceReply.setSelective(true);
sendMessageRequest.setReplayMarkup(forceReply);
sendMessageRequest.setText(CustomMessages.sendDestination);
Message sentMessage = SenderHelper.SendMessage(sendMessageRequest, TOKEN);
if (sentMessage != null) {
DatabaseManager.getInstance().addUserForDirection(message.getFrom().getId(), WATING_DESTINY_STATUS,
sentMessage.getMessageId(), message.getText());
}
if (languageMessages.contains(message.getFrom().getId())) {
onLanguageSelected(message);
} else {
String language = DatabaseManager.getInstance().getUserLanguage(update.getMessage().getFrom().getId());
if (message.getText().startsWith(Commands.setLanguageCommand)) {
onSetLanguageCommand(message, language);
} else if (message.getText().startsWith(Commands.startDirectionCommand)) {
onStartdirectionsCommand(message, language);
} else if ((message.getText().startsWith(Commands.help) ||
(message.getText().startsWith(Commands.startCommand) || !message.isGroupMessage())) &&
DatabaseManager.getInstance().getUserDestinationStatus(message.getFrom().getId()) == -1) {
sendHelpMessage(message, language);
} else if (!message.getText().startsWith("/")) {
if (DatabaseManager.getInstance().getUserDestinationStatus(message.getFrom().getId()) == WATING_ORIGIN_STATUS &&
message.hasReplayMessage() &&
DatabaseManager.getInstance().getUserDestinationMessageId(message.getFrom().getId()) == message.getReplyToMessage().getMessageId()) {
onOriginReceived(message, language);
} else if (DatabaseManager.getInstance().getUserDestinationStatus(message.getFrom().getId()) == WATING_DESTINY_STATUS &&
message.hasReplayMessage() &&
DatabaseManager.getInstance().getUserDestinationMessageId(message.getFrom().getId()) == message.getReplyToMessage().getMessageId()) {
String origin = DatabaseManager.getInstance().getUserOrigin(message.getFrom().getId());
String destiny = message.getText();
String directions = DirectionsService.getInstance().getDirections(origin, destiny);
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setChatId(message.getChatId());
ReplyKeyboardHide replyKeyboardHide = new ReplyKeyboardHide();
replyKeyboardHide.setSelective(true);
sendMessageRequest.setReplayMarkup(replyKeyboardHide);
sendMessageRequest.setReplayToMessageId(message.getMessageId());
sendMessageRequest.setText(directions);
Message sentMessage = SenderHelper.SendMessage(sendMessageRequest, TOKEN);
if (sentMessage != null) {
DatabaseManager.getInstance().deleteUserForDirections(message.getFrom().getId());
}
} else if (!message.hasReplayMessage()) {
if (DatabaseManager.getInstance().getUserDestinationStatus(message.getFrom().getId()) == -1) {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(CustomMessages.helpDirections);
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
} else {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(CustomMessages.youNeedReplyDirections);
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
} else if (DatabaseManager.getInstance().getUserDestinationStatus(message.getFrom().getId()) == WATING_DESTINY_STATUS &&
message.hasReplayMessage() &&
DatabaseManager.getInstance().getUserDestinationMessageId(message.getFrom().getId()) == message.getReplyToMessage().getMessageId()) {
onDestinationReceived(message, language);
} else if (!message.hasReplayMessage()) {
if (DatabaseManager.getInstance().getUserDestinationStatus(message.getFrom().getId()) == -1) {
sendHelpMessage(message, language);
} else {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(LocalisationService.getInstance().getString("youNeedReplyDirections", language));
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
}
}
}
}
}
private void onDestinationReceived(Message message, String language) {
String origin = DatabaseManager.getInstance().getUserOrigin(message.getFrom().getId());
String destiny = message.getText();
List<String> directions = DirectionsService.getInstance().getDirections(origin, destiny, language);
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setChatId(message.getChatId());
ReplyKeyboardHide replyKeyboardHide = new ReplyKeyboardHide();
replyKeyboardHide.setSelective(true);
sendMessageRequest.setReplayMarkup(replyKeyboardHide);
sendMessageRequest.setReplayToMessageId(message.getMessageId());
Message sentMessage = null;
for (String direction : directions) {
sendMessageRequest.setText(direction);
sentMessage = SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
if (sentMessage != null) {
DatabaseManager.getInstance().deleteUserForDirections(message.getFrom().getId());
}
}
private void onOriginReceived(Message message, String language) {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setChatId(message.getChatId());
sendMessageRequest.setReplayToMessageId(message.getMessageId());
ForceReplyKeyboard forceReplyKeyboard = new ForceReplyKeyboard();
forceReplyKeyboard.setSelective(true);
sendMessageRequest.setReplayMarkup(forceReplyKeyboard);
sendMessageRequest.setText(LocalisationService.getInstance().getString("sendDestination", language));
Message sentMessage = SenderHelper.SendMessage(sendMessageRequest, TOKEN);
if (sentMessage != null) {
DatabaseManager.getInstance().addUserForDirection(message.getFrom().getId(), WATING_DESTINY_STATUS,
sentMessage.getMessageId(), message.getText());
}
}
private void sendHelpMessage(Message message, String language) {
SendMessage sendMessageRequest = new SendMessage();
String helpDirectionsFormated = String.format(
LocalisationService.getInstance().getString("helpDirections", language),
Commands.startDirectionCommand);
sendMessageRequest.setText(helpDirectionsFormated);
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
private void onStartdirectionsCommand(Message message, String language) {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setChatId(message.getChatId());
sendMessageRequest.setReplayToMessageId(message.getMessageId());
ForceReplyKeyboard forceReplyKeyboard = new ForceReplyKeyboard();
forceReplyKeyboard.setSelective(true);
sendMessageRequest.setReplayMarkup(forceReplyKeyboard);
sendMessageRequest.setText(LocalisationService.getInstance().getString("initDirections", language));
Message sentMessage = SenderHelper.SendMessage(sendMessageRequest, TOKEN);
if (sentMessage != null) {
DatabaseManager.getInstance().addUserForDirection(message.getFrom().getId(), WATING_ORIGIN_STATUS,
sentMessage.getMessageId(), null);
}
}
private void onSetLanguageCommand(Message message, String language) {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setChatId(message.getChatId());
ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup();
HashMap<String, String> languages = LocalisationService.getInstance().getSupportedLanguages();
List<List<String>> commands = new ArrayList<>();
for (Map.Entry<String, String> entry : languages.entrySet()) {
List<String> commandRow = new ArrayList<>();
commandRow.add(entry.getKey() + " --> " + entry.getValue());
commands.add(commandRow);
}
replyKeyboardMarkup.setResizeKeyboard(true);
replyKeyboardMarkup.setOneTimeKeyboad(true);
replyKeyboardMarkup.setKeyboard(commands);
replyKeyboardMarkup.setSelective(true);
sendMessageRequest.setReplayMarkup(replyKeyboardMarkup);
sendMessageRequest.setText(LocalisationService.getInstance().getString("chooselanguage", language));
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
languageMessages.add(message.getFrom().getId());
}
private void onLanguageSelected(Message message) {
String[] parts = message.getText().split("-->", 2);
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setChatId(message.getChatId());
if (LocalisationService.getInstance().getSupportedLanguages().containsKey(parts[0].trim())) {
DatabaseManager.getInstance().putUserLanguage(message.getFrom().getId(), parts[0].trim());
sendMessageRequest.setText(LocalisationService.getInstance().getString("languageModified", parts[0].trim()));
} else {
sendMessageRequest.setText(LocalisationService.getInstance().getString("errorLanguage"));
}
sendMessageRequest.setReplayToMessageId(message.getMessageId());
ReplyKeyboardHide replyKeyboardHide = new ReplyKeyboardHide();
replyKeyboardHide.setHideKeyboard(true);
replyKeyboardHide.setSelective(true);
sendMessageRequest.setReplayMarkup(replyKeyboardHide);
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
languageMessages.remove(message.getFrom().getId());
}
}

278
src/main/java/org/telegram/updateshandlers/FilesHandlers.java

@ -1,12 +1,18 @@
package org.telegram.updateshandlers;
import org.telegram.*;
import org.telegram.BotConfig;
import org.telegram.BuildVars;
import org.telegram.Commands;
import org.telegram.SenderHelper;
import org.telegram.api.Message;
import org.telegram.api.ReplyKeyboardHide;
import org.telegram.api.ReplyKeyboardMarkup;
import org.telegram.api.Update;
import org.telegram.database.DatabaseManager;
import org.telegram.methods.SendDocument;
import org.telegram.methods.SendMessage;
import org.telegram.services.Emoji;
import org.telegram.services.LocalisationService;
import org.telegram.updatesreceivers.UpdatesThread;
import org.telegram.updatesreceivers.Webhook;
@ -14,6 +20,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* @author Ruben Bermudez
@ -23,16 +30,17 @@ import java.util.Map;
*/
public class FilesHandlers implements UpdatesCallback {
private static final String TOKEN = BotConfig.TOKENFILES;
private static final int webhookPort = 9992;
private static final String webhookPath = "filesBot";
private static final int INITIAL_UPLOAD_STATUS = 0;
private static final int DELETE_UPLOADED_STATUS = 1;
private final Webhook webhook;
private final UpdatesThread updatesThread;
private final ConcurrentLinkedQueue<Integer> languageMessages = new ConcurrentLinkedQueue<>();
public FilesHandlers() {
if (BuildVars.useWebHook) {
webhook = new Webhook(this, webhookPort);
webhook = new Webhook(this, webhookPath);
updatesThread = null;
SenderHelper.SendWebhook(webhook.getURL(), TOKEN);
} else {
@ -47,112 +55,194 @@ public class FilesHandlers implements UpdatesCallback {
handleFileUpdate(update);
}
@Override
public void onUpdatesReceived(List<Update> updates) {
for (Update update: updates) {
handleFileUpdate(update);
}
}
public void handleFileUpdate(Update update) {
Message message = update.getMessage();
if (message != null && message.hasText()) {
String[] parts = message.getText().split(" ", 2);
if (parts[0].startsWith(Commands.startCommand)) {
if (parts.length == 2) {
if (DatabaseManager.getInstance().doesFileExists(parts[1].trim())) {
SendDocument sendDocumentRequest = new SendDocument();
sendDocumentRequest.setDocument(parts[1].trim());
sendDocumentRequest.setChatId(message.getChatId());
SenderHelper.SendDocument(sendDocumentRequest, TOKEN);
} else {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(CustomMessages.wrongFileId);
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
if (languageMessages.contains(message.getFrom().getId())) {
onLanguageReceived(message);
} else {
String language = DatabaseManager.getInstance().getUserLanguage(update.getMessage().getFrom().getId());
if (message.getText().startsWith(Commands.setLanguageCommand)) {
onSetLanguageCommand(message, language);
} else {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(CustomMessages.helpFiles);
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
} else if (!message.isGroupMessage()){
if (parts[0].startsWith(Commands.uploadCommand)) { // Open upload for user
DatabaseManager.getInstance().addUserForFile(message.getFrom().getId(), INITIAL_UPLOAD_STATUS);
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(CustomMessages.sendFileToUpload);
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
} else if (parts[0].startsWith(Commands.cancelCommand)) {
DatabaseManager.getInstance().deleteUserForFile(message.getFrom().getId());
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(CustomMessages.processFinished);
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
} else if (parts[0].startsWith(Commands.deleteCommand)) {
if (DatabaseManager.getInstance().getUserStatusForFile(message.getFrom().getId()) == DELETE_UPLOADED_STATUS &&
parts.length == 2) {
String[] innerParts = parts[1].split("-->", 2);
boolean removed = DatabaseManager.getInstance().deleteFile(innerParts[0].trim());
SendMessage sendMessageRequest = new SendMessage();
if (removed) {
sendMessageRequest.setText(CustomMessages.fileDeleted);
String[] parts = message.getText().split(" ", 2);
if (parts[0].startsWith(Commands.startCommand)) {
if (parts.length == 2) {
onStartWithParameters(message, language, parts[1]);
} else {
sendMessageRequest.setText(CustomMessages.wrongFileId);
sendHelpMessage(message, language);
}
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
DatabaseManager.getInstance().deleteUserForFile(message.getFrom().getId());
} else {
DatabaseManager.getInstance().addUserForFile(message.getFrom().getId(), DELETE_UPLOADED_STATUS);
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(CustomMessages.deleteUploadedFile);
sendMessageRequest.setChatId(message.getChatId());
HashMap<String, String> files = DatabaseManager.getInstance().getFilesByUser(message.getFrom().getId());
ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup();
if (files.size() > 0) {
List<List<String>> commands = new ArrayList<>();
for (Map.Entry<String, String> entry : files.entrySet()) {
List<String> commandRow = new ArrayList<>();
commandRow.add(Commands.deleteCommand + " " + entry.getKey() + " --> " + entry.getValue());
commands.add(commandRow);
}
replyKeyboardMarkup.setResizeKeyboard(true);
replyKeyboardMarkup.setOneTimeKeyboad(true);
replyKeyboardMarkup.setKeyboard(commands);
}
sendMessageRequest.setReplayMarkup(replyKeyboardMarkup);
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
} else if (parts[0].startsWith(Commands.listCommand)) {
HashMap<String, String> files = DatabaseManager.getInstance().getFilesByUser(message.getFrom().getId());
SendMessage sendMessageRequest = new SendMessage();
if (files.size() > 0) {
String text = CustomMessages.listOfFiles + ":\n\n";
for (Map.Entry<String, String> entry : files.entrySet()) {
text += CustomMessages.uploadedFileURL + entry.getKey() + " --> " + entry.getValue() + "\n";
} else if (!message.isGroupMessage()) {
if (parts[0].startsWith(Commands.uploadCommand)) { // Open upload for user
onUploadCommand(message, language);
} else if (parts[0].startsWith(Commands.cancelCommand)) {
onCancelCommand(message, language);
} else if (parts[0].startsWith(Commands.deleteCommand)) {
onDeleteCommand(message, language, parts);
} else if (parts[0].startsWith(Commands.listCommand)) {
onListCommand(message, language);
} else {
sendHelpMessage(message, language);
}
sendMessageRequest.setText(text);
} else {
sendMessageRequest.setText(CustomMessages.noFiles);
}
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
} else {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(CustomMessages.helpFiles);
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
}
} else if ( message != null && message.hasDocument()
} else if (message != null && message.hasDocument()
&& DatabaseManager.getInstance().getUserStatusForFile(message.getFrom().getId()) == INITIAL_UPLOAD_STATUS) {
String language = DatabaseManager.getInstance().getUserLanguage(update.getMessage().getFrom().getId());
DatabaseManager.getInstance().addFile(message.getDocument().getFileId(), message.getFrom().getId(), message.getDocument().getFileName());
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(CustomMessages.fileUploaded + CustomMessages.uploadedFileURL + message.getDocument().getFileId());
sendMessageRequest.setText(LocalisationService.getInstance().getString("fileUploaded", language) +
LocalisationService.getInstance().getString("uploadedFileURL", language) + message.getDocument().getFileId());
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
}
private void onListCommand(Message message, String language) {
HashMap<String, String> files = DatabaseManager.getInstance().getFilesByUser(message.getFrom().getId());
SendMessage sendMessageRequest = new SendMessage();
if (files.size() > 0) {
String text = LocalisationService.getInstance().getString("listOfFiles", language) + ":\n\n";
for (Map.Entry<String, String> entry : files.entrySet()) {
text += LocalisationService.getInstance().getString("uploadedFileURL", language)
+ entry.getKey() + " " + Emoji.LEFT_RIGHT_ARROW.toString() + " " + entry.getValue() + "\n";
}
sendMessageRequest.setText(text);
} else {
sendMessageRequest.setText(LocalisationService.getInstance().getString("noFiles", language));
}
sendMessageRequest.setChatId(message.getChatId());
ReplyKeyboardHide replyKeyboardHide = new ReplyKeyboardHide();
replyKeyboardHide.setHideKeyboard(true);
sendMessageRequest.setReplayMarkup(replyKeyboardHide);
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
private void onDeleteCommand(Message message, String language, String[] parts) {
if (DatabaseManager.getInstance().getUserStatusForFile(message.getFrom().getId()) == DELETE_UPLOADED_STATUS &&
parts.length == 2) {
onDeleteCommandWithParameters(message, language, parts[1]);
} else {
onDeleteCommandWithoutParameters(message, language);
}
}
private void onDeleteCommandWithoutParameters(Message message, String language) {
DatabaseManager.getInstance().addUserForFile(message.getFrom().getId(), DELETE_UPLOADED_STATUS);
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(LocalisationService.getInstance().getString("deleteUploadedFile", language));
sendMessageRequest.setChatId(message.getChatId());
HashMap<String, String> files = DatabaseManager.getInstance().getFilesByUser(message.getFrom().getId());
ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup();
if (files.size() > 0) {
List<List<String>> commands = new ArrayList<>();
for (Map.Entry<String, String> entry : files.entrySet()) {
List<String> commandRow = new ArrayList<>();
commandRow.add(Commands.deleteCommand + " " + entry.getKey() + " " + Emoji.LEFT_RIGHT_ARROW.toString()
+ " " + entry.getValue());
commands.add(commandRow);
}
replyKeyboardMarkup.setResizeKeyboard(true);
replyKeyboardMarkup.setOneTimeKeyboad(true);
replyKeyboardMarkup.setKeyboard(commands);
}
sendMessageRequest.setReplayMarkup(replyKeyboardMarkup);
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
private void onDeleteCommandWithParameters(Message message, String language, String part) {
String[] innerParts = part.split(Emoji.LEFT_RIGHT_ARROW.toString(), 2);
boolean removed = DatabaseManager.getInstance().deleteFile(innerParts[0].trim());
SendMessage sendMessageRequest = new SendMessage();
if (removed) {
sendMessageRequest.setText(LocalisationService.getInstance().getString("fileDeleted", language));
} else {
sendMessageRequest.setText(LocalisationService.getInstance().getString("wrongFileId", language));
}
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
DatabaseManager.getInstance().deleteUserForFile(message.getFrom().getId());
}
private void onCancelCommand(Message message, String language) {
DatabaseManager.getInstance().deleteUserForFile(message.getFrom().getId());
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(LocalisationService.getInstance().getString("processFinished", language));
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
private void onUploadCommand(Message message, String language) {
DatabaseManager.getInstance().addUserForFile(message.getFrom().getId(), INITIAL_UPLOAD_STATUS);
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(LocalisationService.getInstance().getString("sendFileToUpload", language));
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
private void sendHelpMessage(Message message, String language) {
SendMessage sendMessageRequest = new SendMessage();
String formatedString = String.format(
LocalisationService.getInstance().getString("helpFiles", language),
Commands.startCommand, Commands.uploadCommand, Commands.deleteCommand,
Commands.listCommand);
sendMessageRequest.setText(formatedString);
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
private void onStartWithParameters(Message message, String language, String part) {
if (DatabaseManager.getInstance().doesFileExists(part.trim())) {
SendDocument sendDocumentRequest = new SendDocument();
sendDocumentRequest.setDocument(part.trim());
sendDocumentRequest.setChatId(message.getChatId());
SenderHelper.SendDocument(sendDocumentRequest, TOKEN);
} else {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(LocalisationService.getInstance().getString("wrongFileId", language));
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
}
private void onSetLanguageCommand(Message message, String language) {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setChatId(message.getChatId());
ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup();
HashMap<String, String> languages = LocalisationService.getInstance().getSupportedLanguages();
List<List<String>> commands = new ArrayList<>();
for (Map.Entry<String, String> entry : languages.entrySet()) {
List<String> commandRow = new ArrayList<>();
commandRow.add(entry.getKey() + " " + Emoji.LEFT_RIGHT_ARROW.toString() + " " + entry.getValue());
commands.add(commandRow);
}
replyKeyboardMarkup.setResizeKeyboard(true);
replyKeyboardMarkup.setOneTimeKeyboad(true);
replyKeyboardMarkup.setKeyboard(commands);
replyKeyboardMarkup.setSelective(true);
sendMessageRequest.setReplayMarkup(replyKeyboardMarkup);
sendMessageRequest.setText(LocalisationService.getInstance().getString("chooselanguage", language));
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
languageMessages.add(message.getFrom().getId());
}
private void onLanguageReceived(Message message) {
String[] parts = message.getText().split(Emoji.LEFT_RIGHT_ARROW.toString(), 2);
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setChatId(message.getChatId());
if (LocalisationService.getInstance().getSupportedLanguages().containsKey(parts[0].trim())) {
DatabaseManager.getInstance().putUserLanguage(message.getFrom().getId(), parts[0].trim());
sendMessageRequest.setText(LocalisationService.getInstance().getString("languageModified", parts[0].trim()));
} else {
sendMessageRequest.setText(LocalisationService.getInstance().getString("errorLanguage"));
}
sendMessageRequest.setReplayToMessageId(message.getMessageId());
ReplyKeyboardHide replyKeyboardHide = new ReplyKeyboardHide();
replyKeyboardHide.setHideKeyboard(true);
replyKeyboardHide.setSelective(true);
sendMessageRequest.setReplayMarkup(replyKeyboardHide);
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
languageMessages.remove(message.getFrom().getId());
}
}

28
src/main/java/org/telegram/updateshandlers/TransifexHandlers.java

@ -3,8 +3,10 @@ package org.telegram.updateshandlers;
import org.telegram.*;
import org.telegram.api.Message;
import org.telegram.api.Update;
import org.telegram.database.DatabaseManager;
import org.telegram.methods.SendDocument;
import org.telegram.methods.SendMessage;
import org.telegram.services.LocalisationService;
import org.telegram.services.TransifexService;
import org.telegram.updatesreceivers.UpdatesThread;
import org.telegram.updatesreceivers.Webhook;
@ -19,13 +21,13 @@ import java.util.List;
*/
public class TransifexHandlers implements UpdatesCallback {
private static final String TOKEN = BotConfig.TOKENTRANSIFEX;
private static final int webhookPort = 9991;
private static final String webhookPath = "transifexBot";
private final Webhook webhook;
private final UpdatesThread updatesThread;
public TransifexHandlers() {
if (BuildVars.useWebHook) {
webhook = new Webhook(this, webhookPort);
webhook = new Webhook(this, webhookPath);
updatesThread = null;
SenderHelper.SendWebhook(webhook.getURL(), TOKEN);
} else {
@ -40,16 +42,10 @@ public class TransifexHandlers implements UpdatesCallback {
sendTransifexFile(update);
}
@Override
public void onUpdatesReceived(List<Update> updates) {
for (Update update: updates) {
sendTransifexFile(update);
}
}
public void sendTransifexFile(Update update) {
Message message = update.getMessage();
if (message != null && message.hasText()) {
String language = DatabaseManager.getInstance().getUserLanguage(update.getMessage().getFrom().getId());
String text = message.getText();
String[] parts = text.split(" ", 2);
SendDocument sendDocument = null;
@ -70,7 +66,12 @@ public class TransifexHandlers implements UpdatesCallback {
sendDocument = TransifexService.getInstance().getAndroidSupportLanguageFile(parts[1].trim());
} else if (parts[0].startsWith(Commands.help)) {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(CustomMessages.helpTransifex);
String helpFormated = String.format(
LocalisationService.getInstance().getString("helpTransifex", language),
Commands.transifexiOSCommand, Commands.transifexAndroidCommand, Commands.transifexWebogram,
Commands.transifexTDesktop, Commands.transifexOSX, Commands.transifexWP,
Commands.transifexAndroidSupportCommand);
sendMessageRequest.setText(helpFormated);
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}
@ -82,7 +83,12 @@ public class TransifexHandlers implements UpdatesCallback {
} else if (parts[0].startsWith(Commands.help) ||
(message.getText().startsWith(Commands.startCommand) || !message.isGroupMessage())) {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setText(CustomMessages.helpTransifex);
String helpFormated = String.format(
LocalisationService.getInstance().getString("helpTransifex", language),
Commands.transifexiOSCommand, Commands.transifexAndroidCommand, Commands.transifexWebogram,
Commands.transifexTDesktop, Commands.transifexOSX, Commands.transifexWP,
Commands.transifexAndroidSupportCommand);
sendMessageRequest.setText(helpFormated);
sendMessageRequest.setChatId(message.getChatId());
SenderHelper.SendMessage(sendMessageRequest, TOKEN);
}

1
src/main/java/org/telegram/updateshandlers/UpdatesCallback.java

@ -12,5 +12,4 @@ import java.util.List;
*/
public interface UpdatesCallback {
void onUpdateReceived(Update update);
void onUpdatesReceived(List<Update> updates);
}

1228
src/main/java/org/telegram/updateshandlers/WeatherHandlers.java

File diff suppressed because it is too large

101
src/main/java/org/telegram/updatesreceivers/UpdatesThread.java

@ -2,25 +2,31 @@ package org.telegram.updatesreceivers;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.telegram.BuildVars;
import org.telegram.api.Update;
import org.telegram.database.DatabaseManager;
import org.telegram.methods.Constants;
import org.telegram.methods.GetUpdates;
import org.telegram.services.BotLogger;
import org.telegram.updateshandlers.UpdatesCallback;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.TimeUnit;
/**
* @author Ruben Bermudez
@ -29,37 +35,50 @@ import java.util.List;
* @date 20 of June of 2015
*/
public class UpdatesThread {
private static volatile BotLogger log = BotLogger.getLogger(UpdatesThread.class.getName());
private final UpdatesCallback callback;
private final ReaderThread readerThread;
private final HandlerThread handlerThread;
private int lastReceivedUpdate;
private String token;
private final ConcurrentLinkedDeque<Update> receivedUpdates = new ConcurrentLinkedDeque<>();
public UpdatesThread(String token, UpdatesCallback callback) {
this.token = token;
this.callback = callback;
this.lastReceivedUpdate = -1;
if (BuildVars.useWebHook) {
this.readerThread = null;
} else {
this.readerThread = new ReaderThread();
this.readerThread.start();
}
this.lastReceivedUpdate = DatabaseManager.getInstance().getLastUpdate(this.token);
this.readerThread = new ReaderThread();
this.readerThread.start();
this.handlerThread = new HandlerThread();
this.handlerThread.start();
}
private class ReaderThread extends Thread {
@Override
public void run() {
setPriority(Thread.MIN_PRIORITY);
while(true) {
GetUpdates request = new GetUpdates();
request.setOffset(lastReceivedUpdate+1);
CloseableHttpClient httpclient = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
request.setLimit(100);
request.setTimeout(20);
request.setOffset(lastReceivedUpdate + 1);
CloseableHttpClient httpclient = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).setConnectionTimeToLive(20, TimeUnit.SECONDS).build();
String url = Constants.BASEURL + token + "/" + GetUpdates.PATH;
HttpGet httpGet = new HttpGet(url + request.getUrlParams());
httpGet.addHeader("Content-type", "application/x-www-form-urlencoded");
httpGet.addHeader("charset", "UTF-8");
HttpResponse response;
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> nameValuePairs = new ArrayList<>();
nameValuePairs.add(new BasicNameValuePair(GetUpdates.OFFSET_FIELD, request.getOffset()+""));
nameValuePairs.add(new BasicNameValuePair(GetUpdates.LIMIT_FIELD, request.getLimit()+""));
if (request.getTimeout() != null) {
nameValuePairs.add(new BasicNameValuePair(GetUpdates.TIMEOUT_FIELD, request.getTimeout()+""));
}
try {
response = httpclient.execute(httpGet);
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
httpPost.addHeader("Content-type", "application/x-www-form-urlencoded");
httpPost.addHeader("charset", "UTF-8");
HttpResponse response;
log.debug(httpPost.toString());
response = httpclient.execute(httpPost);
HttpEntity ht = response.getEntity();
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
@ -71,39 +90,63 @@ public class UpdatesThread {
throw new InvalidObjectException(jsonObject.toString());
}
JSONArray jsonArray = jsonObject.getJSONArray("result");
log.debug(jsonArray.toString());
if (jsonArray.length() != 0) {
List<Update> updates = new ArrayList<Update>();
for (int i = 0; i < jsonArray.length(); i++) {
Update update = new Update(jsonArray.getJSONObject(i));
if (update.getUpdateId() > lastReceivedUpdate) {
lastReceivedUpdate = update.getUpdateId();
receivedUpdates.addFirst(update);
}
updates.add(update);
}
callback.onUpdatesReceived(updates);
synchronized (receivedUpdates) {
receivedUpdates.notifyAll();
}
} else {
try {
synchronized (this) {
this.wait(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
log.error(e);
continue;
}
}
} catch (JSONException e) {
try {
synchronized (this) {
this.wait(500);
log.warning(e);
}
} catch (IOException e) {
log.warning(e);
}
}
}
}
private class HandlerThread extends Thread {
@Override
public void run() {
setPriority(Thread.MIN_PRIORITY);
while(true) {
try {
Update update = receivedUpdates.pollLast();
if (update == null) {
synchronized (receivedUpdates) {
try {
receivedUpdates.wait();
} catch (InterruptedException e) {
log.error(e);
continue;
}
update = receivedUpdates.pollLast();
if (update == null) {
continue;
}
} catch (InterruptedException e1) {
e.printStackTrace();
continue;
}
}
} catch (IOException e) {
e.printStackTrace();
DatabaseManager.getInstance().putLastUpdate(token, update.getUpdateId());
callback.onUpdateReceived(update);
} catch (Exception e) {
log.error(e);
}
}
}

21
src/main/java/org/telegram/updatesreceivers/Webhook.java

@ -8,6 +8,7 @@ import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.telegram.BuildVars;
import org.telegram.services.BotLogger;
import org.telegram.updateshandlers.UpdatesCallback;
import java.io.IOException;
@ -20,14 +21,17 @@ import java.net.URI;
* @date 20 of June of 2015
*/
public class Webhook {
private static volatile BotLogger log = BotLogger.getLogger(Webhook.class.getName());
private static final int PORT = 443;
private static final String KEYSTORE_SERVER_FILE = "./keystore_server";
private static final String KEYSTORE_SERVER_PWD = "asdfgh";
private final URI URL;
private final int port;
private final String path;
public Webhook(UpdatesCallback callback, int webhookPort) {
this.port = webhookPort;
public Webhook(UpdatesCallback callback, String webhookPath) {
this.path = webhookPath;
RestApi restApi = new RestApi(callback);
SSLContextConfigurator sslContext = new SSLContextConfigurator();
@ -40,8 +44,6 @@ public class Webhook {
rc.register(JacksonFeature.class);
rc.property(JSONConfiguration.FEATURE_POJO_MAPPING, true);
URL = getBaseURI();
final HttpServer grizzlyServer = GrizzlyHttpServerFactory.createHttpServer(
getBaseURI(),
rc,
@ -49,15 +51,16 @@ public class Webhook {
new SSLEngineConfigurator(sslContext).setClientMode(false).setNeedClientAuth(false));
try {
grizzlyServer.start();
} catch (IOException ignored) {
} catch (IOException e) {
log.error(e);
}
}
private URI getBaseURI() {
return URI.create(BuildVars.INTERNALWEBHOOKURL + ":" + this.port);
return URI.create(String.format("%s:%d/%s", BuildVars.INTERNALWEBHOOKURL, PORT, this.path));
}
public String getURL() {
return String.format("%s:%d/callback", BuildVars.BASEWEBHOOKURL, this.port);
return String.format("%s/%s/callback", BuildVars.BASEWEBHOOKURL, this.path);
}
}

85
src/main/resources/localisation/strings.properties

@ -0,0 +1,85 @@
helpTransifex= Tricks with words is the game that I play, give it a shot, I might make your day.\n\nTo get the latest Telegram localization file for a language: \n|-- %s LANG_CODE : Get the latest iOS language.\n|-- %s LANG_CODE : Get the latest Android language.\n|-- %s LANG_CODE : Get the latest Webogram language.\n|-- %s LANG_CODE : Get the latest Tdesktop language.\n|-- %s LANG_CODE : Get the latest OSX-App language.\n|-- %s LANG_CODE : Get the latest Windows Phone language.\n\n2. To get an updated localization file for your Android beta-app: \n|-- %s LANG_CODE : Get the latest Android-beta language.
helpFiles= Leaving a file for some others to find? Just dock your boat here and a bay comes to mind.\n\nShare files through a custom link: \n|-- %s FILEID : Get a file by id.\n|-- %s : Start your file upload.\n|-- %s : Select one of your files to delete it.\n|-- %s : Show a list of your shared files.
helpDirections= The road ahead, paved with good intentions, the right path ahead however, is what I tend to mention.\n\nTo get directions between two locations: \n|-- %s : Start to get directions
sendFileToUpload= Please send me a file you want to share. Make sure you attach it as file, not as an image or video.
fileUploaded= Great, your file has been uploaded. Send this link to anyone you want and they will be able to download the file:\n\n
deleteUploadedFile= Please select the file you want to delete:
fileDeleted= The file was deleted
wrongFileId= Sorry, we can't find a file with that ID. Either a typo was made or it was deleted already.
listOfFiles= This your currently shared list of files:
noFiles= You haven't shared any files yet.
processFinished= The current process was cancelled.
uploadedFileURL= https://telegram.me/filesbot?start=
initDirections= Please reply to this message with your starting point.
sendDestination= Please reply to this message with your destination.
youNeedReplyDirections= I'm sorry, I can't help you unless you reply to the message I sent you.
chooselanguage= Please, select a language from the list to change to that language.
errorLanguage= We don't support that language or a typo was made. The process has been cancelled.
directionsInit= %s is %s away from %s and it takes %s to arrive there, following these directions:\n\n
directionsNotFound= Directions not found between %s and %s.
errorFetchingDirections= Error fetching directions info
directionsStep= %s during %s (%s)
languageModified= Your language setting has been updated.
helpWeatherMessage= Curious about the weather?\
\nJust send me these commands and you'll know a lot better\:\
\n\t\t%s Get the current weather for a location or city\
\n\t\t%s Get a 3-day forecast for a location or city\
\n\t\t%s Set current alerts\
\n\t\t%s Select a forecast-language\
\n\t\t%s Change your unit preferences
forecast=%sForecast
current=%sCurrent
help=%sHelp
settings=%sSettings
cancel=%sCancel
location=%sLocation
new=%sNew
languages=%sLanguages
alerts=%sAlerts
units=%sUnits
back=%sBack
delete=%sDelete
showList=%sShow list
rateMe=%sRate me
metricSystem=Metric System
imperialSystem= Imperial System
selectLanguage=Your current language is %s. Select a language from the list to change to that language.
languageUpdated=Your language setting has been updated.
errorLanguageNotFound= We don't support that language or a typo was made. Please select one from the list.
selectUnits=Your current unit setting is %s. Select an option from the list to change it.
unitsUpdated=Your unit settings have been updated.
errorUnitsNotFound= We don't support that unit system or a typo was made. Please select one from the list.
onWeatherNewCommand=Please send me the city you are interested in, please use this format: CITY,COUNTRY
onWeatherLocationCommand=Please send me the location you are interested in.
onCurrentCommandFromHistory=Select an option from your recent requests, "new" to send a new city or "location" to send me a location to get current weather.
onCurrentCommandWithoutHistory=Select "new" to send a new city or "location" to send me a location to get current weather.
onForecastCommandFromHistory=Select an option from your recent requests, "new" to send a new city or "location" to send me a location to get 3-day weather forecast.
onForecastCommandWithoutHistory=Select "new" to send a new city or "location" to send me a location to get a 3-day weather forecast.
weatherCurrent= The weather for %s is:\n\n %s
currentWeatherPartMetric=\t- Weather: %s\n\t- Cloudiness: %s\n\t- Temperature: %s ºC\n\n
currentWeatherPartImperial=\t- Weather: %s\n\t- Cloudiness: %s\n\t- Temperature: %s ºF\n\n
weatherForcast= The weather for %s will be:\n\n %s
forecastWeatherPartMetric= %s On %s \n\t- Forecast: %s\n\t- High temperature: %s ºC\n\t- Low temperature: %s ºC\n\n
forecastWeatherPartImperial= %s On %s \n\t- Forecast: %s\n\t- High temperature: %s ºF\n\t- Low temperature: %s ºF\n\n
weatherAlert= The weather for %s will be:\n\n %s
alertWeatherPartMetric=\t- Forecast: %s\n\t- High temperature: %s ºC\n\t- Low temperature: %s ºC\n\n
alertWeatherPartImperial=\t- Forecast: %s\n\t- High temperature: %s ºF\n\t- Low temperature: %s ºF\n\n
chooseOption=Please, select an option from the menu.
backToMainMenu=Process cancelled, back to main menu.
onSettingsCommand=Please, select an option:\
\n\t\t%s Languages: Select a forecast-language\
\n\t\t%s Units: Select your preferred units\
\n\t\t%s Alerts: Set daily alerts\
\n\t\t%s Back: Return to main menu
alertsMenuMessage=Here you can manage your alerts or add new ones.
chooseNewAlertCity=Which city do you want to set an alert for? Select an option from your recent requests.
newAlertSaved=%s Your alert for %s has been correctly created, you will receive the weather update twice a day.
initialAlertList=You have %d alerts:\n\n%s
partialAlertList=%s%s\n
noAlertList=I couldn't find any alert for you.
alertDeleted=The selected alert has been deleted.
cityNotFound= City not found
errorFetchingWeather= We're sorry, there was an error fetching the weather.
rateMeMessage=If you like this bot, please rate it at https://telegram.me/storebot?start=weatherbot

75
src/main/resources/localisation/strings_es.properties

@ -0,0 +1,75 @@
helpTransifex= Magia con las palabras es lo que se me da bien, quizás te alegre el día.\n\nObtén los últimos archivos de localización de Telegram en tu idioma\:\n|-- %s CÓDIGO_IDIOMA \: Obtén el idioma para iOS.\n|-- %s CÓDIGO_IDIOMA \: Obtén el idioma para Android.\n|-- %s CÓDIGO_IDIOMA \: Obtén el idioma para Webogram.\n|-- %s CÓDIGO_IDIOMA \: Obtén el idioma para Tdesktop.\n|-- %s CÓDIGO_IDIOMA \: Obtén el idioma para OS X.\n|-- %s CÓDIGO_IDIOMA \: Obtén el idioma para Windows Phone.\n\n 2. Obtén un archivo de localización actualizado para tu beta de Android\:\n|-- %s CÓDIGO_IDIOMA\: Obtén el idioma para Android beta.
helpFiles= ¿Quieres compartir un archivo con alguien? Has llegado al puerto adecuado. \n\nComparte archivos usando un enlace personalizado\: \n|-- %s \: ID_ARCHIVO \: Obtener un archivo por id. \n|-- %s \: Iniciar la subida de un archivo. \n|-- %s \: Elige y elimina uno de tus archivos.\n|-- %s \: Muestra una lista de tus archivos compartidos.
helpDirections= Un viaje por delante es una buena ocasión, ¿pero no sería mejor conociendo el camino?\n\nPara obtener la ruta que debes seguir entre dos lugares\:\n|-- %s \: Comienza a obtener la ruta
sendFileToUpload= Por favor, envíame el archivo que quieres compartir. Asegúrate de adjuntarlo como archivo, no como imagen o vídeo.
fileUploaded= Perfecto, ya tengo tu archivo. Envía este link a cualquiera que desees que lo tenga y podrá descargarlo\:\n\n
deleteUploadedFile= Por favor, selecciona un archivo de la lista para eliminarlo\:
fileDeleted= El archivo fue eliminado
wrongFileId= Lo siento, no podemos encontrar el archivo con ese ID. Puede que haya un error o que el archivo haya sido eliminado.
listOfFiles= Esta es la lista actual de tus archivos compartidos\:
noFiles= Aún no has compartido ningún archivo.
processFinished= El proceso actual ha sido cancelado.
uploadedFileURL= https\://telegram.me/filesbot?start\=
initDirections= Por favor, responde a este mensaje con el lugar de salida.
sendDestination= Por favor, responde a este mensaje con el lugar de destino.
youNeedReplyDirections= Lo siento, no puedo ayudarte a menos que respondas al mensaje que te he enviado.
chooselanguage= Por favor, elige un idioma de la lista para cambiar a ese idioma.
errorLanguage= No soportamos ese idioma o ha habido un error. El proceso ha sido cancelado.
directionsInit= %s está a %s de %s y se necesita %s para llegar, siguiendo estas direcciones\:\n\n
directionsNotFound= No hemos encontrado una ruta desde %s hasta %s.
errorFetchingDirections= Ha habido un error obteniendo la ruta
directionsStep= %s durante %s (%s)
languageModified= Tus ajustes de idioma fueron actualizados.
helpWeatherMessage= ¿Te interesa el estado del tiempo?\nEnvíame estos comandos y te mantendré informado\:\n\t\t%s Obtén el tiempo actual \n\t\t%s Obtén el pronóstico para 3 días \n\t\t%s Establece alertas\n\t\t%s Elige un idioma\n\t\t%s Cambia las unidades
forecast=%sPronóstico
current=%sTiempo actual
help=%sAyuda
settings=%sAjustes
cancel=%sCancelar
location=%sUbicación
new=%sNueva
languages=%sIdiomas
alerts=%sAlertas
units=%sUnidades
back=%sAtrás
delete=%sEliminar
showList=%sMostrar lista
rateMe=%sPuntúame
metricSystem=Sistema métrico
imperialSystem= Sistema imperial
selectLanguage=Tu idioma actual es %s. Elige un idioma de la lista para usarlo.
languageUpdated=Tus ajustes de idioma fueron actualizados.
errorLanguageNotFound= No soportamos ese idioma o se cometió un error ortográfico. Por favor elige uno de la lista.
selectUnits=Tu sistema de unidades actual es %s. Elige una opción de la lista para cambiarlo.
unitsUpdated=Tus ajustes de unidades fueron actualizados.
errorUnitsNotFound= No soportamos ese sistema de unidades o se cometió un error ortográfico. Por favor elige uno de la lista.
onWeatherNewCommand=Por favor, envíame la ciudad en la que estas interesado, usa este formato\: CIUDAD,PAÍS
onWeatherLocationCommand=Por favor, envíame la ubicación en la que estás interesado.
onCurrentCommandFromHistory=Elige una opción de tu solicitudes recientes, "nueva" para enviar una nueva ciudad o "ubicación" para enviarme una ubicación para obtener el tiempo actual.
onCurrentCommandWithoutHistory=Elige "nueva" para enviar una nueva ciudad o "ubicación" para enviarme una ubicación para obtener el tiempo actual.
onForecastCommandFromHistory=Elige una opción de tus solicitudes recientes, "nueva" para enviar una ciudad o "ubicación"
onForecastCommandWithoutHistory=Elige "nueva" para enviar una nueva ciudad o "ubicación"
weatherCurrent= El tiempo para %s es\:\n\n%s
currentWeatherPartMetric=\t- Tiempo\: %s\n\t- Nubes\: %s\n\t-Temperatura\: %s ºC
currentWeatherPartImperial=\t- Tiempo\: %s\n\t- Nubes\: %s\n\t-Temperatura\: %s ºF
weatherForcast= El tiempo para %s será\:\n\n%s
forecastWeatherPartMetric= %s el %s\n- Pronóstico\: %s\n\t- Temperatura máxima\: %s ºC\n\t- Temperatura mínima\: %s ºC\n
forecastWeatherPartImperial= %s el %s\n- Pronóstico\: %s\n\t- Temperatura máxima\: %s ºF\n\t- Temperatura mínima\: %s ºF\n
weatherAlert= El tiempo para %s será\:\n\n%s
alertWeatherPartMetric=\t- Pronóstico\: %s\n\t- Temperatura máxima\: %s ºC\n\t- Temperatura mínima\: %s ºC\n
alertWeatherPartImperial=\t- Pronóstico\: %s\n\t- Temperatura máxima\: %s ºF\n\t- Temperatura mínima\: %s ºF\n
chooseOption=Por favor, elige una opción del menú.
backToMainMenu=Proceso cancelado, vuelta al menú principal.
onSettingsCommand=Por favor, elige una opción\:\n\t\t%s Idiomas\: elige un idioma\n\t\t%s Unidades\: cambia las unidades\n\t\t%s Alertas\: establece alertas diarias\n\t\t%s Atrás\: vuelve al menú principal
alertsMenuMessage=Aquí puedes administrar tus alertas o añadir nuevas.
chooseNewAlertCity=¿Para qué ciudad quieres establecer una alerta? Elige una opción de tus solicitudes recientes.
newAlertSaved=%s Tu alerta para %s fue añadida correctamente, recibirás actualizaciones del tiempo dos veces al día.
initialAlertList=Tienes %d alertas\:\n\n%s
partialAlertList=%s%s\n
noAlertList=No pude encontrar ninguna alerta.
alertDeleted=La alerta seleccionada fue eliminada.
cityNotFound= Ciudad no encontrada
errorFetchingWeather= Lo sentimos, hubo un error solicitando el tiempo.
rateMeMessage=Si te gusta este bot, por favor, puntúalo en https\://telegram.me/storebot?start\=weatherbot

75
src/main/resources/localisation/strings_nl.properties

@ -0,0 +1,75 @@
helpTransifex= Schieten woorden tekort of heb je last van een babylonische dwaling? Probeer mij dan eens uit voor een Telegram-vertaling.\n\nOm de laatste vertaling voor Telegram te verkrijgen voor een taal\:\n|-- %s TAAL_CODE \: De meest recente iOS-vertaling.\n|-- %s TAAL_CODE \: De meest recente Android-vertaling\n|-- %s TAAL_CODE \: De meest recente Webogram-vertaling.\n|-- %s TAAL_CODE \: De meest recente Tdesktop-vertaling.\n|-- %s TAAL_CODE \: De meest recente OSX-vertaling.\n|-- %s TAAL_CODE \: De meest recente Windows Phone-vertaling.\n\n2. Alleen voor Android beta in je huidige taal\:\n|-- %s TAAL_CODE \: De meest Android-beta vertaling\n\n(TAAL_CODE voorbeeld\: nl)
helpFiles= Het downloadverbod is van kracht want Brein greep de macht, je downloads zijn nu officieel illegaal, maar een bestandje met mij delen, zodat anderen het kunnen vinden, is dat eigenlijk wel zo abnormaal?\n\nBestanden delen via een link\:\n|-- %s BESTANDSID \: Ontvang een bestand met ID.\n|-- %s \: Begin een bestandsupload.\n|-- %s \: Kies een bestand om te verwijderen.\n|-- %s \: Geef een lijst met gedeelde bestanden weer.
helpDirections= Vele wegen leiden naar Rome, maar terug naar Leiden is toch nog een hele klus, bent u het zoeken op de kaart al zat? Vraag het aan mij en ik breng u op het rechte pad\!\n\nOm een routebeschrijving tussen twee locaties te ontvangen\:\n|-- %s \: Start een routebeschrijving.
sendFileToUpload= Stuur mij het bestand dat je wilt delen. Zorg ervoor dat je het stuurt als een bestand en niet als een afbeelding of video.
fileUploaded= Je bestand is geüpload. Stuur deze link naar iedereen die je maar wilt en zij kunnen het bestand ermee downloaden\:\n\n
deleteUploadedFile= Selecteer het bestand dat je wilt verwijderen\:
fileDeleted= Het bestand is verwijderd.
wrongFileId= Sorry, ik kan het bestand met dat ID niet vinden. Mogelijk is er een typefout gemaakt of is het bestand al verwijderd.
listOfFiles= Dit zijn je gedeelde bestanden op het moment\:
noFiles= Je hebt nog geen bestanden gedeeld.
processFinished= Het huidige proces is geannuleerd.
uploadedFileURL= https\://telegram.me/filesbot?start\=
initDirections= Beantwoord dit bericht met je vertrekpunt.
sendDestination= Beantwoord dit bericht met je bestemming.
youNeedReplyDirections= Het spijt me, ik kan je niet helpen tenzij je het bericht dat ik stuurde beantwoord.
chooselanguage= Kies een taal uit de lijst om de taal te wijzigen.
errorLanguage= Deze taal ondersteunen we niet of je hebt een typefout gemaakt. Het proces is geannuleerd.
directionsInit= %s is %s verwijderd van %s en het duurt %s om er te komen met de volgende routebeschrijving\:\n\n
directionsNotFound= Routebeschrijving tussen %s en %s niet gevonden.
errorFetchingDirections= Ophalen van routebeschrijving mislukt
directionsStep= %s voor %s (%s)
languageModified= Je taalinstelling is bijgewerkt.
helpWeatherMessage= Zon of regen, hagel of ijs?\nVraag het aan mij en ik maak u weer wijs\!\n\n\t\t%s Om de huidige weersvoorspelling te ontvangen\n\t\t%s Voor een drie-daagse weersvoorspelling\n\t\t%s Waarschuwingen instellen\n\t\t%s Kies een weersvoorspellingstaal\n\t\t%s Kies een eenhedenstelsel
forecast=%sVoorspelling
current=%sHuidig
help=%sHelp
settings=%sInstellingen
cancel=%sAnnuleren
location=%sLocatie
new=%sNieuw
languages=%sTalen
alerts=%sWaarschuwingen
units=%sEenheden
back=%sTerug
delete=%sVerwijderen
showList=%sLijst weergeven
rateMe=%sBeoordeel mij
metricSystem=Metriek stelsel
imperialSystem= Imperiaal stelsel
selectLanguage=Je huidige taal is %s. Kies een taal van de lijst om deze instelling te wijzigen.
languageUpdated=Je taalinstelling is bijgewerkt.
errorLanguageNotFound= Deze taal ondersteunen we niet of je hebt een typefout gemaakt. Kies een taal uit de lijst.
selectUnits=Je huidige eenhedenstelsel is %s. Kies een optie van de lijst om deze instelling te wijzigen.
unitsUpdated=Je gekozen eenheid is bijgewerkt.
errorUnitsNotFound= Dit stelsel ondersteunen we helaas niet, of je hebt een typefout gemaakt. Kies een stelsel van de lijst.
onWeatherNewCommand=Stuur me de stad waarin je geïnteresseerd bent. Gebruik dit formaat\: STAD,LAND
onWeatherLocationCommand=Stuur me de locatie waarin je geïnteresseerd bent.
onCurrentCommandFromHistory=Kies een optie van je recente verzoeken, "nieuw" om een stad te sturen of "locatie" om mij een locatie te sturen en de huidige weersvoorspelling te ontvangen.
onCurrentCommandWithoutHistory=Kies "nieuw" om een stad te sturen of "locatie" om mij een locatie te sturen de huidige weersvoorspelling te ontvangen.
onForecastCommandFromHistory=Kies een optie van je recente verzoeken, "nieuw" om een stad te sturen of "locatie" om mij een locatie te sturen en een drie-daagse weersvoorspelling te ontvangen.
onForecastCommandWithoutHistory=Kies "nieuw" om een stad te sturen of "locatie" om mij een locatie te sturen en een drie-daagse weersvoorspelling te ontvangen.
weatherCurrent= De weersverwachting voor %s is\:\n\n%s
currentWeatherPartMetric=\t- Weer\: %s\n\t- Bewolking\: %s\n\t- Temperatuur\: %s ºC\n
currentWeatherPartImperial=\t- Weer\: %s\n\t- Bewolking\: %s\n\t- Temperatuur\: %s ºF\n
weatherForcast= De weersverwachting voor %s\:\n\n%s
forecastWeatherPartMetric= %s op %s \n\t- Voorspelling\: %s\n\t- Hoogste temperatuur\: %s ºC\n\t- Laagste temperatuur\: %s ºC\n
forecastWeatherPartImperial= %s on %s \n\t- Voorspelling\: %s\n\t- Hoogste temperatuur\: %s ºF\n\t- Laagste temperatuur\: %s ºF\n
weatherAlert= De weersverwachting voor %s\:\n\n%s
alertWeatherPartMetric=\t- Voorspelling\: %s\n\t- Hoogste temperatuur\: %s ºC\n\t- Laagste temperatuur\: %s ºC\n
alertWeatherPartImperial=\t- Voorspelling\: %s\n\t- Hoogste temperatuur\: %s ºF\n\t- Laagste temperatuur\: %s ºF\n
chooseOption=Selecteer een optie uit het menu.
backToMainMenu=Proces geannuleerd, terug naar het hoofdmenu.
onSettingsCommand=Maak een keuze\:\n\t\t%s Taal\: Kies een weersvoorspellings-taal\n\t\t%s Eenheid\: Wijzig je voorkeurseenheid.\n\t\t%s Alerts\: dagelijkse waarschuwingen instellen\n\t\t%s Back\: Terug naar het hoofdmenu
alertsMenuMessage=Hier kan je je waarschuwingen beheren of nieuwe toevoegen.
chooseNewAlertCity=Voor welke stad wil je een waarschuwing instellen? Kies een optie van je recente verzoeken.
newAlertSaved=%s Je waarschuwing voor %s is aangemaakt, je ontvangt twee keer per dag een weersvoorspelling.
initialAlertList=Je hebt %d waarschuwingen\:\n\n%s
partialAlertList=%s%s\n
noAlertList=Geen waarschuwingen gevonden.
alertDeleted=De geselecteerde waarschuwing is verwijderd.
cityNotFound= Stad niet gevonden.
errorFetchingWeather= Sorry, er is iets misgegaan bij het ophalen van het weer.
rateMeMessage=Als je deze bot leuk vindt dan kan je hem hier beoordelen https\://telegram.me/storebot?start\=weatherbot

75
src/main/resources/localisation/strings_pt.properties

@ -0,0 +1,75 @@
helpTransifex= Para obter a última tradução para os aplicativos do Telegram em um idioma\:\n|-- %s CODIGO_DO_IDIOMA\: Obter a última tradução para iOS.\n|-- %s CODIGO_DO_IDIOMA\: Obter a última tradução para Android.\n|-- %s CODIGO_DO_IDIOMA\: Obter a última tradução para Webogram.\n|-- %s CODIGO_DO_IDIOMA\: Obter a última tradução para TDesktop.\n|-- %s CODIGO_DO_IDIOMA\: Obter a última tradução para OSX.\n|-- %s CODIGO_DO_IDIOMA\: Obter a última tradução para Windows Phone.\n\n2. Para obter a o arquivo de tradução atualizado para o seu aplicativo beta do Android\:\n|-- %s CODIGO_DO_IDIOMA\: Obter a última tradução para Android-beta.
helpFiles= Deseja compartilhar um arquivo com outras pessoas? Você está no lugar certo\!\n\nCompartilhe arquivos através de um link\:\n|-- %s IDDOARQUIVO \: Obter arquivo pelo id.\n|-- %s \: Iniciar seu upload de arquivo.\n|-- %s \: Escolher um de seus arquivos para apagar.\n|-- %s \: Mostrar lista de seus arquivos compartilhados.
helpDirections= A estrada à frente, cheia de boas intenções, o caminho logo à frente no entanto, é o que eu tendo a mencionar.\n\nPara obter localizações entre dois locais\:\n|-- %s \: Começar para receber as direções
sendFileToUpload= Por favor, envie-me o arquivo que deseja compartilhar. Certifique-se de anexá-lo como arquivo, e não como uma imagem ou vídeo.
fileUploaded= Ótimo, seu arquivo foi carregado. Envie esse link para qualquer um que quiser e eles poderão baixar o seu arquivo\:\n\n
deleteUploadedFile= Por favor, selecione o arquivo que deseja apagar\:
fileDeleted= O arquivo foi deletado
wrongFileId= Desculpe, não conseguimos achar o arquivo com esse ID. Houve algum erro ao digitar ou o arquivo já foi deletado.
listOfFiles= Essa é sua lista de arquivos compartilhados atualmente\:
noFiles= Você não compartilhou arquivos ainda.
processFinished= O processo atual foi cancelado.
uploadedFileURL= https\://telegram.me/filesbot?start\=
initDirections= Por favor, responda a essa mensagem com seu ponto de partida.
sendDestination= Por favor, responda a essa mensagem com seu destino.
youNeedReplyDirections= Me desculpe, não consigo ajudá-lo a menos que você responda a mensagem que lhe enviei.
chooselanguage= Por favor, escolha um idioma da lista para alterar para essa linguagem;
errorLanguage= Nós não temos suporte para essa linguagem ou ela foi escrita errada. Esse processo foi cancelado.
directionsInit= %s é %s distante de %s e demora %s para chegar lá, seguindo essas direções\:\n\n
directionsNotFound= Direções não encontradas entre %s e %s
errorFetchingDirections= Erro ao obter informações de direção.
directionsStep= %s durante %s (%s)
languageModified= Sua configuração de idioma foi atualizada.
helpWeatherMessage= Curioso sobre o clima?\nBasta me enviar esses comandos e você saberá muito mais.\n\n\t\t%s Obter o clima atual de uma localização ou cidade\n\t\t%s Obter a previsão de 3 dias de uma localização ou cidade\n\t\t%s Definir alertas atuais\n\t\t%s Selecionar um idioma para a previsão\n\t\t%s Alterar suas preferências de unidade
forecast=%sPrevisão
current=%sAtual
help=%sAjuda
settings=%sConfiguração
cancel=%sCancelar
location=%sLocalização
new=%sNovo
languages=%sIdiomas
alerts=%sAlertas
units=%sUnidades
back=%sVoltar
delete=%sApagar
showList=%sMostrar lista
rateMe=%sMe avalie
metricSystem=Sistema Métrico
imperialSystem= Sistema Imperial
selectLanguage=Seu idioma atual é %s. Selecione um idioma da lista para alterar para essa linguagem.
languageUpdated=Sua configuração de idioma foi atualizada.
errorLanguageNotFound= Nós não temos suporte para essa linguagem ou ela foi escrita errada. Por favor, selecione um idioma da lista.
selectUnits=Sua unidade atual é %s. Selecione uma opção da lista para alterar.
unitsUpdated=Sua configuração de unidade foi atualizada.
errorUnitsNotFound= Nós não temos suporte para essa unidade ou ela foi escrita errada. Por favor, selecione um tipo de unidade da lista.
onWeatherNewCommand=Envie-me a cidade e país que você está interessado, use o formato\: CIDADE,PAÍS
onWeatherLocationCommand=Por favor, selecione a localização que você está interessado.
onCurrentCommandFromHistory=Selecione uma opção de suas solicitações recentes, "novo" para enviar uma nova cidade ou "localização" para me enviar seu local e obter o clima atual.
onCurrentCommandWithoutHistory=Selecione "novo" para enviar uma nova cidade ou "localização" para me enviar a localização e obter o clima atual.
onForecastCommandFromHistory=Selecione uma opção de suas solicitações recentes, "novo" para enviar uma nova cidade ou "localização" para me enviar seu local e obter a previsão de 3 dias.
onForecastCommandWithoutHistory=Selecione "novo" para enviar uma nova cidade ou "localização" para me enviar seu local e obter a previsão de 3 dias.
weatherCurrent= O clima para %s é de\:\n\n%s
currentWeatherPartMetric=\t- Clima\: %s\n\t- Nebulosidade\: %s\n\t- Clima\: %s ºC\n\n
currentWeatherPartImperial=\t- Clima\: %s\n\t- Nebulosidade\: %s\n\t- Temperatura\: %s ºF\n\n
weatherForcast= O clima para %s será de\:\n\n%s
forecastWeatherPartMetric= %s Em %s \n\t- Previsão\: %s\n\t- Máxima\: %s ºC\n\t- Mínima\: %s ºC\n\n
forecastWeatherPartImperial= %s Em %s \n\t- Previsão\: %s\n\t- Máxima\: %s ºF\n\t- Mínima\: %s ºF\n\n
weatherAlert= O clima para %s será de\:\n\n%s
alertWeatherPartMetric=\t- Previsão\: %s\n\t- Máxima\: %s ºC\n\t- Mínima\: %s ºC\n\n
alertWeatherPartImperial=\t- Previsão\: %s\n\t- Máxima\: %s ºF\n\t- Mínima\: %s ºF\n\n
chooseOption=Por favor, selecione uma opção do menu.
backToMainMenu=Processo cancelado, de volta ao menu principal.
onSettingsCommand=Por favor, selecione uma opção\:\n\t\t%s Idiomas\: Selecione um idioma para a previsão\n\t\t%s Unidades\: Selecione sua unidade preferida\n\t\t%s Alertas\: Definir alertas diários\n\t\t%s Voltar\: Voltar ao menu principal
alertsMenuMessage=Aqui você pode alterar ou adicionar novos alertas.
chooseNewAlertCity=Para qual cidade você deseja definir um alerta? Selecione uma opção de suas solicitações recentes.
newAlertSaved=%s Seu alerta para %s foi criado corretamente, você irá receber atualizações sobre o clima duas vezes ao dia.
initialAlertList=Você tem %d alertas\:\n\n%s
partialAlertList=%s%s\n
noAlertList=Eu não consegui encontrar nenhum alerta para você.
alertDeleted=O alerta selecionado foi apagado.
cityNotFound= Cidade não encontrada
errorFetchingWeather= Desculpe, houve um erro ao obter o clima.
rateMeMessage=Se você gosta deste bot, por favor nos avalie em https\://telegram.me/storebot?start\=weatherbot
Loading…
Cancel
Save