diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 2b44d22..38c7409 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,6 +2,8 @@ \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index d190f54..c3a5faa 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,117 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -129,49 +44,147 @@ + + - - + + - + - - + + - - + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + - - + + - - + + + + + - - + + @@ -182,8 +195,9 @@ @@ -200,7 +214,7 @@ - + @@ -211,57 +225,57 @@ @@ -355,16 +369,106 @@ + + Abstraction issuesJava + + + Assignment issuesJava + + + Class metricsJava + + + Class structureJava + + + Cloning issuesJava + + + Code style issuesJava + + + CodeSpring CoreSpring + + + Concurrency annotation issuesJava + + + Declaration redundancyJava + + + Encapsulation issuesJava + + + GeneralJavaScript + + + ImportsJava + + + Inheritance issuesJava + + + Initialization issuesJava + + + JBoss Seam issues + + + JUnit issuesJava + Java + + Java EE issues + + + JavaScript + + + Logging issuesJava + + + Memory issuesJava + + + Naming conventionsJava + + + Numeric issuesJava + + + Performance issuesJava + Probable bugsJava + + Security issuesJava + + + Serialization issuesJava + + + Spring + + + Spring CoreSpring + + + Threading issuesJava + + + UI Form Problems + + + Visibility issuesJava + - MalformedFormatString + FieldMayBeStatic @@ -394,7 +498,6 @@ - @@ -445,9 +548,138 @@ + @@ -461,12 +693,12 @@ - + - + @@ -474,6 +706,8 @@ + + @@ -482,7 +716,9 @@ + + @@ -863,7 +1099,31 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + 1434854005227 @@ -973,11 +1233,119 @@ - - @@ -990,7 +1358,7 @@ - + @@ -999,55 +1367,59 @@ - + - + - - + + - - + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1062,11 +1434,6 @@ - - - - - @@ -1079,502 +1446,627 @@ - + + file://$PROJECT_DIR$/src/main/java/org/telegram/services/WeatherService.java + 172 + + + + jar://$MAVEN_REPOSITORY$/org/glassfish/grizzly/grizzly-framework/2.3.19/grizzly-framework-2.3.19-sources.jar!/org/glassfish/grizzly/ssl/SSLContextConfigurator.java + 359 + + + + file://$PROJECT_DIR$/src/main/java/org/telegram/services/TransifexService.java + 323 + + - file://$PROJECT_DIR$/src/main/java/org/telegram/api/PhotoSize.java - 32 + file://$PROJECT_DIR$/src/main/java/org/telegram/updateshandlers/DirectionsHandlers.java + 65 - - file://$PROJECT_DIR$/src/main/java/org/telegram/services/WeatherService.java - 124 + file://$PROJECT_DIR$/src/main/java/org/telegram/updateshandlers/DirectionsHandlers.java + 59 - - file://$PROJECT_DIR$/src/main/java/org/telegram/services/DirectionsService.java - 69 + file://$PROJECT_DIR$/src/main/java/org/telegram/updateshandlers/DirectionsHandlers.java + 56 - - file://$PROJECT_DIR$/src/main/java/org/telegram/services/DirectionsService.java - 78 + file://$PROJECT_DIR$/src/main/java/org/telegram/database/DatabaseManager.java + 119 - - jar://$MAVEN_REPOSITORY$/org/glassfish/grizzly/grizzly-framework/2.3.19/grizzly-framework-2.3.19-sources.jar!/org/glassfish/grizzly/ssl/SSLContextConfigurator.java - 359 + file://$PROJECT_DIR$/src/main/java/org/telegram/updateshandlers/WeatherHandlers.java + 376 - - file://$PROJECT_DIR$/src/main/java/org/telegram/updatesreceivers/Webhook.java - 60 + file://$PROJECT_DIR$/src/main/java/org/telegram/updateshandlers/WeatherHandlers.java + 106 - - - + + + + + + + - + - + - - + + - + - - - + + - + - - - + + - + - - - + + - + - - + - + - - + - + - - + + - + - - + + - + - - - + + - + - - - - - - - - - - - - + + - + - - + - + - - + - + - - + + + - + - - + + - + - - + + - + - - + + - + - - - + + - - - - - + + + + + + + + + - + - - - - - + + - + - - - - - + + - - - - - - - + + + + + + + + + - + - - - - - + + - + - - - - - + + - + - - - - - + + - + - - - + + - + - - - - - + + - + - - - + + - + - - - - - + + - + - - - + + - + - - - - - + + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + - - - - - + + + + + + + + + - + - - - + + - + - - + + - - - + + + + + + + + + + + + + + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - + + + - + - - + + - + - - - - - - - + + + - + - - + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - - + + - - - - - - - - + + + - - - - + + - + + + + - - + + - + + + + - - + + - + + + + - - - - - + + + diff --git a/src/main/java/org/telegram/Commands.java b/src/main/java/org/telegram/Commands.java index 7ac5bb6..8c71e7f 100644 --- a/src/main/java/org/telegram/Commands.java +++ b/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"; } diff --git a/src/main/java/org/telegram/CustomMessages.java b/src/main/java/org/telegram/CustomMessages.java deleted file mode 100644 index d5e85b4..0000000 --- a/src/main/java/org/telegram/CustomMessages.java +++ /dev/null @@ -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"; -} diff --git a/src/main/java/org/telegram/SenderHelper.java b/src/main/java/org/telegram/SenderHelper.java index fa6c770..05bb846 100644 --- a/src/main/java/org/telegram/SenderHelper.java +++ b/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 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); } } diff --git a/src/main/java/org/telegram/api/Contact.java b/src/main/java/org/telegram/api/Contact.java index 8d7d4a5..53b893b 100644 --- a/src/main/java/org/telegram/api/Contact.java +++ b/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); } } diff --git a/src/main/java/org/telegram/api/Document.java b/src/main/java/org/telegram/api/Document.java index 16f7735..23274c3 100644 --- a/src/main/java/org/telegram/api/Document.java +++ b/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); diff --git a/src/main/java/org/telegram/api/ForceReply.java b/src/main/java/org/telegram/api/ForceReplyKeyboard.java similarity index 93% rename from src/main/java/org/telegram/api/ForceReply.java rename to src/main/java/org/telegram/api/ForceReplyKeyboard.java index 3143bfc..6c7ec94 100644 --- a/src/main/java/org/telegram/api/ForceReply.java +++ b/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); diff --git a/src/main/java/org/telegram/api/Message.java b/src/main/java/org/telegram/api/Message.java index acc2562..8761a15 100644 --- a/src/main/java/org/telegram/api/Message.java +++ b/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 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(); + 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 getNewChatPhoto() { return newChatPhoto; } - public void setNewChatPhoto(String newChatPhoto) { + public void setNewChatPhoto(List newChatPhoto) { this.newChatPhoto = newChatPhoto; } diff --git a/src/main/java/org/telegram/api/Sticker.java b/src/main/java/org/telegram/api/Sticker.java index 781794c..a5e756e 100644 --- a/src/main/java/org/telegram/api/Sticker.java +++ b/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); } } diff --git a/src/main/java/org/telegram/api/Video.java b/src/main/java/org/telegram/api/Video.java index 5b826b0..a0a2607 100644 --- a/src/main/java/org/telegram/api/Video.java +++ b/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; - } } diff --git a/src/main/java/org/telegram/database/CreationStrings.java b/src/main/java/org/telegram/database/CreationStrings.java index 5fb2621..59a2fb5 100644 --- a/src/main/java/org/telegram/database/CreationStrings.java +++ b/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 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));"; } diff --git a/src/main/java/org/telegram/database/DatabaseManager.java b/src/main/java/org/telegram/database/DatabaseManager.java index 28a175b..fd5b168 100644 --- a/src/main/java/org/telegram/database/DatabaseManager.java +++ b/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 getRecentWeather(Integer userId) { - HashMap recentWeather = new HashMap<>(); + public List getRecentWeather(Integer userId) { + List 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 getAlertCitiesNameByUser(int userId) { + List 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 getAllAlerts() { + List 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; + } } diff --git a/src/main/java/org/telegram/methods/SendSticker.java b/src/main/java/org/telegram/methods/SendSticker.java index cd94814..3b703ee 100644 --- a/src/main/java/org/telegram/methods/SendSticker.java +++ b/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; + } } diff --git a/src/main/java/org/telegram/methods/SendVideo.java b/src/main/java/org/telegram/methods/SendVideo.java index 30c578d..7357a20 100644 --- a/src/main/java/org/telegram/methods/SendVideo.java +++ b/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"; diff --git a/src/main/java/org/telegram/services/BotLogger.java b/src/main/java/org/telegram/services/BotLogger.java index 84e77ed..9568050 100644 --- a/src/main/java/org/telegram/services/BotLogger.java +++ b/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 instances = new ConcurrentHashMap<>(); - private final Logger logger; - private LocalDateTime lastFileDate; + private final static ConcurrentLinkedQueue 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 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(); + } + } + } } diff --git a/src/main/java/org/telegram/services/CustomTimerTask.java b/src/main/java/org/telegram/services/CustomTimerTask.java new file mode 100644 index 0000000..f387092 --- /dev/null +++ b/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(); +} diff --git a/src/main/java/org/telegram/services/DirectionsService.java b/src/main/java/org/telegram/services/DirectionsService.java index 6b9219f..20f750b 100644 --- a/src/main/java/org/telegram/services/DirectionsService.java +++ b/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 getDirections(String origin, String destination, String language) { + final List 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 getDirectionsSteps(JSONArray steps, String language) { + List 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; } diff --git a/src/main/java/org/telegram/services/Emoji.java b/src/main/java/org/telegram/services/Emoji.java new file mode 100644 index 0000000..cbe2c32 --- /dev/null +++ b/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(); + } +} diff --git a/src/main/java/org/telegram/services/LocalisationService.java b/src/main/java/org/telegram/services/LocalisationService.java new file mode 100644 index 0000000..afc2cf3 --- /dev/null +++ b/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 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 getSupportedLanguages() { + return supportedLanguages; + } + + public String getLanguageCodeByName(String language) { + return supportedLanguages.entrySet().stream().filter(x -> x.getValue().equals(language)).findFirst().get().getKey(); + } +} diff --git a/src/main/java/org/telegram/services/TimerExecutor.java b/src/main/java/org/telegram/services/TimerExecutor.java new file mode 100644 index 0000000..1f87ce4 --- /dev/null +++ b/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); + } + } +} diff --git a/src/main/java/org/telegram/services/TransifexService.java b/src/main/java/org/telegram/services/TransifexService.java index 1b58f1a..e5519a2 100644 --- a/src/main/java/org/telegram/services/TransifexService.java +++ b/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; } diff --git a/src/main/java/org/telegram/services/WeatherService.java b/src/main/java/org/telegram/services/WeatherService.java index 3d8c2b9..d96c1d0 100644 --- a/src/main/java/org/telegram/services/WeatherService.java +++ b/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; + } } diff --git a/src/main/java/org/telegram/structure/WeatherAlert.java b/src/main/java/org/telegram/structure/WeatherAlert.java new file mode 100644 index 0000000..bbf8c7b --- /dev/null +++ b/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; + } +} diff --git a/src/main/java/org/telegram/updateshandlers/DirectionsHandlers.java b/src/main/java/org/telegram/updateshandlers/DirectionsHandlers.java index 6e79bd4..7efd862 100644 --- a/src/main/java/org/telegram/updateshandlers/DirectionsHandlers.java +++ b/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 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 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 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 languages = LocalisationService.getInstance().getSupportedLanguages(); + List> commands = new ArrayList<>(); + for (Map.Entry entry : languages.entrySet()) { + List 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()); + } } diff --git a/src/main/java/org/telegram/updateshandlers/FilesHandlers.java b/src/main/java/org/telegram/updateshandlers/FilesHandlers.java index 3e2e170..e55237b 100644 --- a/src/main/java/org/telegram/updateshandlers/FilesHandlers.java +++ b/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 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 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 files = DatabaseManager.getInstance().getFilesByUser(message.getFrom().getId()); - ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup(); - if (files.size() > 0) { - List> commands = new ArrayList<>(); - for (Map.Entry entry : files.entrySet()) { - List 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 files = DatabaseManager.getInstance().getFilesByUser(message.getFrom().getId()); - SendMessage sendMessageRequest = new SendMessage(); - if (files.size() > 0) { - String text = CustomMessages.listOfFiles + ":\n\n"; - for (Map.Entry 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 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 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 files = DatabaseManager.getInstance().getFilesByUser(message.getFrom().getId()); + ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup(); + if (files.size() > 0) { + List> commands = new ArrayList<>(); + for (Map.Entry entry : files.entrySet()) { + List 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 languages = LocalisationService.getInstance().getSupportedLanguages(); + List> commands = new ArrayList<>(); + for (Map.Entry entry : languages.entrySet()) { + List 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()); + } } diff --git a/src/main/java/org/telegram/updateshandlers/TransifexHandlers.java b/src/main/java/org/telegram/updateshandlers/TransifexHandlers.java index 447215b..c483803 100644 --- a/src/main/java/org/telegram/updateshandlers/TransifexHandlers.java +++ b/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 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); } diff --git a/src/main/java/org/telegram/updateshandlers/UpdatesCallback.java b/src/main/java/org/telegram/updateshandlers/UpdatesCallback.java index 04798d7..570acd2 100644 --- a/src/main/java/org/telegram/updateshandlers/UpdatesCallback.java +++ b/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 updates); } diff --git a/src/main/java/org/telegram/updateshandlers/WeatherHandlers.java b/src/main/java/org/telegram/updateshandlers/WeatherHandlers.java index 1be311f..3f3f64c 100644 --- a/src/main/java/org/telegram/updateshandlers/WeatherHandlers.java +++ b/src/main/java/org/telegram/updateshandlers/WeatherHandlers.java @@ -1,23 +1,19 @@ package org.telegram.updateshandlers; -import org.telegram.*; -import org.telegram.api.ForceReply; -import org.telegram.api.Message; -import org.telegram.api.ReplyKeyboardMarkup; -import org.telegram.api.Update; +import org.telegram.BotConfig; +import org.telegram.BuildVars; +import org.telegram.SenderHelper; +import org.telegram.api.*; import org.telegram.database.DatabaseManager; import org.telegram.methods.SendMessage; -import org.telegram.services.BotLogger; -import org.telegram.services.WeatherService; +import org.telegram.services.*; +import org.telegram.structure.WeatherAlert; import org.telegram.updatesreceivers.UpdatesThread; import org.telegram.updatesreceivers.Webhook; +import javax.swing.text.JTextComponent; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; /** * @author Ruben Bermudez @@ -26,153 +22,1109 @@ import java.util.concurrent.ConcurrentLinkedQueue; * @date 24 of June of 2015 */ public class WeatherHandlers implements UpdatesCallback { - private static volatile BotLogger log = BotLogger.getLogger(WeatherHandlers.class.getName()); - private static final String TOKEN = BotConfig.TOKENWEATHER; - private static final int CURRENTWEATHERID = 0; - private static final int FORECASTWEATHERID = 1; - - private static final int webhookPort = 9990; - private final Webhook webhook; - private final UpdatesThread updatesThread; - private ConcurrentHashMap listOfSentMessages = new ConcurrentHashMap<>(); + private static final int MAINMENU = 1; + private static final int CURRENTWEATHER = 2; + private static final int CURRENTNEWWEATHER = 3; + private static final int CURRENTLOCATIONWEATHER = 4; + private static final int FORECASTWEATHER = 5; + private static final int FORECASTNEWWEATHER = 6; + private static final int FORECASTLOCATIONWEATHER = 7; + private static final int ALERT = 8; + private static final int ALERTNEW = 9; + private static final int ALERTDELETE = 10; + private static final int SETTINGS = 11; + private static final int LANGUAGE = 12; + private static final int UNITS = 13; + private static final String webhookPath = "weatherBot"; public WeatherHandlers() { + Webhook webhook; if (BuildVars.useWebHook) { - webhook = new Webhook(this, webhookPort); - updatesThread = null; + webhook = new Webhook(this, webhookPath); SenderHelper.SendWebhook(webhook.getURL(), TOKEN); } else { - webhook = null; SenderHelper.SendWebhook("", TOKEN); - updatesThread = new UpdatesThread(TOKEN, this); + new UpdatesThread(TOKEN, this); + } + startAlertTimers(); + } + + private static void startAlertTimers() { + TimerExecutor.getInstance().startExecutionEveryDayAt(new CustomTimerTask("First day alert", -1) { + @Override + public void execute() { + sendAlerts(); + } + }, 0, 0, 0); + + TimerExecutor.getInstance().startExecutionEveryDayAt(new CustomTimerTask("Second day alert", -1) { + @Override + public void execute() { + sendAlerts(); + } + }, 12, 0, 0); + } + + private static void sendAlerts() { + List allAlerts = DatabaseManager.getInstance().getAllAlerts(); + for (WeatherAlert weatherAlert : allAlerts) { + String[] userOptions = DatabaseManager.getInstance().getUserWeatherOptions(weatherAlert.getUserId()); + String weather = WeatherService.getInstance().fetchWeatherAlert(weatherAlert.getCityId(), + weatherAlert.getUserId(), userOptions[0], userOptions[1]); + SendMessage sendMessage = new SendMessage(); + sendMessage.setChatId(weatherAlert.getUserId()); + sendMessage.setText(weather); + sendBuiltMessage(sendMessage); } } @Override public void onUpdateReceived(Update update) { - sendWeatherInformation(update); + Message message = update.getMessage(); + if (message != null) { + handleIncomingMessage(message); + } } - @Override - public void onUpdatesReceived(List updates) { - for (Update update: updates) { - sendWeatherInformation(update); + private static void onCancelCommand(Integer chatId, Integer userId, Integer messageId, ReplyKeyboard replyKeyboard, String language) { + SendMessage sendMessage = new SendMessage(); + sendMessage.setChatId(chatId); + sendMessage.setReplayMarkup(getMainMenuKeyboard(language)); + sendMessage.setReplayToMessageId(messageId); + sendMessage.setReplayMarkup(replyKeyboard); + sendMessage.setText(LocalisationService.getInstance().getString("backToMainMenu", language)); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(userId, chatId, MAINMENU); + } + + // region Incoming messages handlers + + private static void handleIncomingMessage(Message message) { + final int state = DatabaseManager.getInstance().getWeatherState(message.getFrom().getId(), message.getChatId()); + final String language = DatabaseManager.getInstance().getUserWeatherOptions(message.getFrom().getId())[0]; + switch(state) { + case MAINMENU: + messageOnMainMenu(message, language); + break; + case CURRENTWEATHER: + case CURRENTNEWWEATHER: + case CURRENTLOCATIONWEATHER: + messageOnCurrentWeather(message, language, state); + break; + case FORECASTWEATHER: + case FORECASTNEWWEATHER: + case FORECASTLOCATIONWEATHER: + messageOnForecastWeather(message, language, state); + break; + case ALERT: + case ALERTNEW: + case ALERTDELETE: + messageOnAlert(message, language, state); + break; + case SETTINGS: + messageOnSetting(message, language); + break; + case LANGUAGE: + messageOnLanguage(message, language); + break; + case UNITS: + messageOnUnits(message, language); + break; + default: + sendMessageDefault(message, language); + break; } } - public void sendWeatherInformation(Update update) { - Message message = update.getMessage(); - if (message != null && message.hasText()) { - String text = message.getText(); - String[] parts = text.split(" ", 2); - if (parts[0].startsWith(Commands.WEATHERCOMMAND)) { - if (parts.length == 2) { - String citywithoutdescription = parts[1].split("-->", 2)[0].trim(); - String weather = WeatherService.getInstance().fetchWeatherForecast(citywithoutdescription, message.getFrom().getId()); - SendMessage sendMessageRequest = new SendMessage(); - sendMessageRequest.setText(weather); - sendMessageRequest.setChatId(message.getChatId()); - SenderHelper.SendMessage(sendMessageRequest, TOKEN); - } else { - HashMap recentWeather = DatabaseManager.getInstance().getRecentWeather(message.getFrom().getId()); - SendMessage sendMessageRequest = new SendMessage(); - if (recentWeather.size() > 0) { - ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup(); - List> commands = new ArrayList<>(); - for (Map.Entry entry : recentWeather.entrySet()) { - List commandRow = new ArrayList<>(); - commandRow.add(Commands.WEATHERCOMMAND + " " + entry.getKey() + " --> " + entry.getValue()); - commands.add(commandRow); - } - replyKeyboardMarkup.setResizeKeyboard(true); - replyKeyboardMarkup.setOneTimeKeyboad(true); - replyKeyboardMarkup.setSelective(true); - replyKeyboardMarkup.setKeyboard(commands); - sendMessageRequest.setReplayMarkup(replyKeyboardMarkup); - sendMessageRequest.setText(CustomMessages.chooseFromRecentWeather); - } else { - sendMessageRequest.setText(CustomMessages.pleaseSendMeCityWeather); - ForceReply forceReply = new ForceReply(); - forceReply.setForceReply(true); - forceReply.setSelective(true); - sendMessageRequest.setReplayMarkup(forceReply); - } - sendMessageRequest.setReplayToMessageId(message.getMessageId()); - sendMessageRequest.setChatId(message.getChatId()); - Message sentMessage = SenderHelper.SendMessage(sendMessageRequest, TOKEN); - try { - listOfSentMessages.put(sentMessage.getMessageId(), FORECASTWEATHERID); - } catch(NullPointerException e) { - log.error(e); - } - } - } else if (parts[0].startsWith(Commands.CURRENTWEATHERCOMMAND)) { - if (parts.length == 2) { - String citywithoutdescription = parts[1].split("-->", 2)[0].trim(); - String weather = WeatherService.getInstance().fetchWeatherCurrent(citywithoutdescription, message.getFrom().getId()); - SendMessage sendMessageRequest = new SendMessage(); - sendMessageRequest.setText(weather); - sendMessageRequest.setChatId(message.getChatId()); - SenderHelper.SendMessage(sendMessageRequest, TOKEN); - } else { - HashMap recentWeather = DatabaseManager.getInstance().getRecentWeather(message.getFrom().getId()); - SendMessage sendMessageRequest = new SendMessage(); - if (recentWeather.size() > 0) { - ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup(); - List> commands = new ArrayList<>(); - for (Map.Entry entry : recentWeather.entrySet()) { - List commandRow = new ArrayList<>(); - commandRow.add(Commands.CURRENTWEATHERCOMMAND + " " + entry.getKey() + " --> " + entry.getValue()); - commands.add(commandRow); - } - replyKeyboardMarkup.setResizeKeyboard(true); - replyKeyboardMarkup.setOneTimeKeyboad(true); - replyKeyboardMarkup.setSelective(true); - replyKeyboardMarkup.setKeyboard(commands); - sendMessageRequest.setReplayMarkup(replyKeyboardMarkup); - sendMessageRequest.setText(CustomMessages.chooseFromRecentWeather); - } else { - sendMessageRequest.setText(CustomMessages.pleaseSendMeCityWeather); - ForceReply forceReply = new ForceReply(); - forceReply.setForceReply(true); - forceReply.setSelective(true); - sendMessageRequest.setReplayMarkup(forceReply); - } - sendMessageRequest.setChatId(message.getChatId()); - sendMessageRequest.setReplayToMessageId(message.getMessageId()); - Message sentMessage = SenderHelper.SendMessage(sendMessageRequest, TOKEN); - try { - listOfSentMessages.put(sentMessage.getMessageId(), CURRENTWEATHERID); - } catch(NullPointerException e) { - log.error(e); - } - } - } else if (message.isReply() && listOfSentMessages.contains(message.getReplyToMessage().getMessageId())) { - SendMessage sendMessageRequest = new SendMessage(); - if (listOfSentMessages.remove(message.getReplyToMessage().getMessageId()) == CURRENTWEATHERID) { - String weather = WeatherService.getInstance().fetchWeatherCurrent(message.getText(), message.getFrom().getId()); - sendMessageRequest.setText(weather); - } else { - String weather = WeatherService.getInstance().fetchWeatherForecast(message.getText(), message.getFrom().getId()); - sendMessageRequest.setText(weather); - } - sendMessageRequest.setChatId(message.getChatId()); - SenderHelper.SendMessage(sendMessageRequest, TOKEN); - } else if (parts[0].startsWith(Commands.help) || - (message.getText().startsWith(Commands.startCommand) || !message.isGroupMessage())) { - SendMessage sendMessageRequest = new SendMessage(); - sendMessageRequest.setText(CustomMessages.helpWeather); - sendMessageRequest.setChatId(message.getChatId()); - SenderHelper.SendMessage(sendMessageRequest, TOKEN); + // endregion Incoming messages handlers + + // region Alerts Menu Option selected + + private static void messageOnAlert(Message message, String language, int state) { + switch(state) { + case ALERT: + onAlertOptionSelected(message, language); + break; + case ALERTNEW: + onAlertNewOptionSelected(message, language); + break; + case ALERTDELETE: + onAlertDeleteOptionSelected(message, language); + break; + } + } + + private static void onAlertDeleteOptionSelected(Message message, String language) { + if (message.hasText()) { + if (message.getText().equals(getCancelCommand(language))) { + onAlertDeleteBackOptionSelected(message, language); + } else if (DatabaseManager.getInstance().getAlertCitiesNameByUser(message.getFrom().getId()).contains(message.getText())) { + onAlertDeleteCityOptionSelected(message, language); + } else { + sendChooseOptionMessage(message.getChatId(), message.getMessageId(), getAlertsListKeyboard(message.getFrom().getId(), language), language); + } + } + } + + private static void onAlertDeleteCityOptionSelected(Message message, String language) { + DatabaseManager.getInstance().deleteAlertCity(message.getFrom().getId(), message.getText()); + SendMessage sendMessage = new SendMessage(); + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setChatId(message.getChatId()); + sendMessage.setReplayMarkup(getAlertsKeyboard(language)); + sendMessage.setText(LocalisationService.getInstance().getString("alertDeleted", language)); + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), ALERT); + } + + private static void onAlertDeleteBackOptionSelected(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setChatId(message.getChatId()); + sendMessage.setReplayMarkup(getAlertsKeyboard(language)); + sendMessage.setText(LocalisationService.getInstance().getString("alertsMenuMessage", language)); + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), ALERT); + } + + private static void onAlertNewOptionSelected(Message message, String language) { + if (message.hasText()) { + if (message.getText().equals(getCancelCommand(language))) { + SendMessage sendMessage = new SendMessage(); + sendMessage.setChatId(message.getChatId()); + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setReplayMarkup(getAlertsKeyboard(language)); + sendMessage.setText(LocalisationService.getInstance().getString("alertsMenuMessage", language)); + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), ALERT); + } else { + onNewAlertCityReceived(message, language); } - } else if (message != null && message.hasLocation()) { - String weather = WeatherService.getInstance().fetchWeatherForecastByLocation(message.getLocation().getLongitude(), - message.getLocation().getLatitude(), message.getFrom().getId()); + } + } + + private static void onNewAlertCityReceived(Message message, String language) { + int userId = message.getFrom().getId(); + Integer cityId = DatabaseManager.getInstance().getRecentWeatherIdByCity(userId, message.getText()); + if (cityId != null) { + DatabaseManager.getInstance().createNewWeatherAlert(userId, cityId, message.getText()); SendMessage sendMessageRequest = new SendMessage(); - sendMessageRequest.setText(weather); + sendMessageRequest.setReplayMarkup(getAlertsKeyboard(language)); + sendMessageRequest.setReplayToMessageId(message.getMessageId()); + sendMessageRequest.setText(getChooseNewAlertSetMessage(message.getText(), language)); sendMessageRequest.setChatId(message.getChatId()); - SenderHelper.SendMessage(sendMessageRequest, TOKEN); + sendBuiltMessage(sendMessageRequest); + DatabaseManager.getInstance().insertWeatherState(userId, message.getChatId(), ALERT); + } else { + sendChooseOptionMessage(message.getChatId(), message.getMessageId(), + getRecentsKeyboard(message.getFrom().getId(), language, false), language); + } + } + + private static void onAlertOptionSelected(Message message, String language) { + if (message.hasText()) { + if (message.getText().equals(getNewCommand(language))) { + onNewAlertCommand(message, language); + } else if (message.getText().equals(getDeleteCommand(language))) { + onDeleteAlertCommand(message, language); + } else if (message.getText().equals(getListCommand(language))) { + onListAlertCommand(message, language); + } else if (message.getText().equals(getBackCommand(language))) { + onBackAlertCommand(message, language); + } else { + sendChooseOptionMessage(message.getChatId(), message.getMessageId(), + getAlertsKeyboard(language), language); + } + } + } + + private static void onBackAlertCommand(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + + ReplyKeyboardMarkup replyKeyboardMarkup = getSettingsKeyboard(language); + sendMessage.setReplayMarkup(replyKeyboardMarkup); + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setChatId(message.getChatId()); + sendMessage.setText(getSettingsMessage(language)); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), SETTINGS); + } + + private static void onListAlertCommand(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + + sendMessage.setChatId(message.getChatId()); + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setReplayMarkup(getAlertsKeyboard(language)); + sendMessage.setText(getAlertListMessage(message.getFrom().getId(), language)); + sendMessage.setReplayToMessageId(message.getMessageId()); + + sendBuiltMessage(sendMessage); + } + + private static void onDeleteAlertCommand(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + + sendMessage.setChatId(message.getChatId()); + + ReplyKeyboardMarkup replyKeyboardMarkup = getAlertsListKeyboard(message.getFrom().getId(), language); + if (replyKeyboardMarkup != null) { + sendMessage.setReplayMarkup(replyKeyboardMarkup); + sendMessage.setText(LocalisationService.getInstance().getString("chooseNewAlertCity", language)); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), ALERTDELETE); + } else { + sendMessage.setReplayMarkup(getAlertsKeyboard(language)); + sendMessage.setText(LocalisationService.getInstance().getString("noAlertList", language)); + } + + sendMessage.setReplayToMessageId(message.getMessageId()); + sendBuiltMessage(sendMessage); + } + + private static void onNewAlertCommand(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + + sendMessage.setChatId(message.getChatId()); + sendMessage.setReplayMarkup(getRecentsKeyboard(message.getFrom().getId(), language, false)); + sendMessage.setText(LocalisationService.getInstance().getString("chooseNewAlertCity", language)); + sendMessage.setReplayToMessageId(message.getMessageId()); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), ALERTNEW); + } + + // endregion Alerts Menu Option selected + + // region Settings Menu Option selected + + private static void messageOnSetting(Message message, String language) { + if (message.hasText()) { + if (message.getText().startsWith(getLanguagesCommand(language))) { + onLanguageCommand(message, language); + } else if (message.getText().startsWith(getUnitsCommand(language))) { + onUnitsCommand(message, language); + } else if (message.getText().startsWith(getAlertsCommand(language))) { + onAlertsCommand(message, language); + } else if (message.getText().startsWith(getBackCommand(language))) { + sendMessageDefault(message, language); + } else { + sendChooseOptionMessage(message.getChatId(), message.getMessageId(), + getSettingsKeyboard(language), language); + } + } + } + + private static void onAlertsCommand(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setChatId(message.getChatId()); + sendMessage.setReplayMarkup(getAlertsKeyboard(language)); + sendMessage.setText(LocalisationService.getInstance().getString("alertsMenuMessage", language)); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), ALERT); + } + + private static void onUnitsCommand(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setChatId(message.getChatId()); + sendMessage.setReplayMarkup(getUnitsKeyboard(language)); + sendMessage.setText(getUnitsMessage(message.getFrom().getId(), language)); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), UNITS); + } + + private static void onLanguageCommand(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setChatId(message.getChatId()); + sendMessage.setReplayMarkup(getLanguagesKeyboard(language)); + sendMessage.setText(getLanguageMessage(language)); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), LANGUAGE); + } + + // endregion Settings Menu Option selected + + // region Units Menu Option selected + + private static void messageOnUnits(Message message, String language) { + if (message.hasText()) { + if (message.getText().trim().equals(getCancelCommand(language))) { + onBackUnitsCommand(message, language); + } else if (message.getText().trim().equals(LocalisationService.getInstance().getString("metricSystem", language))) { + onUnitsChosen(message.getFrom().getId(), message.getChatId(), + message.getMessageId(), WeatherService.METRICSYSTEM, language); + } else if (message.getText().trim().equals(LocalisationService.getInstance().getString("imperialSystem", language))) { + onUnitsChosen(message.getFrom().getId(), message.getChatId(), + message.getMessageId(), WeatherService.IMPERIALSYSTEM, language); + } else { + onUnitsError(message.getChatId(), message.getMessageId(), language); + } + } + } + + private static void onBackUnitsCommand(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + + ReplyKeyboardMarkup replyKeyboardMarkup = getSettingsKeyboard(language); + sendMessage.setReplayMarkup(replyKeyboardMarkup); + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setChatId(message.getChatId()); + sendMessage.setText(getSettingsMessage(language)); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), SETTINGS); + } + + private static void onUnitsError(Integer chatId, Integer messageId, String language) { + SendMessage sendMessageRequest = new SendMessage(); + sendMessageRequest.setChatId(chatId); + sendMessageRequest.setReplayMarkup(getUnitsKeyboard(language)); + sendMessageRequest.setText(LocalisationService.getInstance().getString("errorUnitsNotFound", language)); + sendMessageRequest.setReplayToMessageId(messageId); + sendBuiltMessage(sendMessageRequest); + } + + private static void onUnitsChosen(Integer userId, Integer chatId, Integer messageId, String units, String language) { + DatabaseManager.getInstance().putUserWeatherUnitsOption(userId, units); + + SendMessage sendMessageRequest = new SendMessage(); + sendMessageRequest.setChatId(chatId); + sendMessageRequest.setText(LocalisationService.getInstance().getString("unitsUpdated", language)); + sendMessageRequest.setReplayToMessageId(messageId); + sendMessageRequest.setReplayMarkup(getMainMenuKeyboard(language)); + sendBuiltMessage(sendMessageRequest); + + DatabaseManager.getInstance().insertWeatherState(userId, chatId, MAINMENU); + } + + // endregion Units Menu Option selected + + // region Language Menu Option selected + + private static void messageOnLanguage(Message message, String language) { + if (message.hasText()) { + if (message.getText().trim().equals(getCancelCommand(language))) { + onBackLanguageCommand(message, language); + } else if (LocalisationService.getInstance().getSupportedLanguages().values().contains(message.getText().trim())) { + onLanguageChosen(message.getFrom().getId(), message.getChatId(), + message.getMessageId(), message.getText().trim()); + } else { + onLanguageError(message.getChatId(), message.getMessageId(), language); + } + } + } + + private static void onBackLanguageCommand(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + + ReplyKeyboardMarkup replyKeyboardMarkup = getSettingsKeyboard(language); + sendMessage.setReplayMarkup(replyKeyboardMarkup); + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setChatId(message.getChatId()); + sendMessage.setText(getSettingsMessage(language)); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), SETTINGS); + } + + private static void onLanguageError(Integer chatId, Integer messageId, String language) { + SendMessage sendMessageRequest = new SendMessage(); + sendMessageRequest.setChatId(chatId); + sendMessageRequest.setReplayMarkup(getLanguagesKeyboard(language)); + sendMessageRequest.setText(LocalisationService.getInstance().getString("errorLanguageNotFound", language)); + sendMessageRequest.setReplayToMessageId(messageId); + sendBuiltMessage(sendMessageRequest); + } + + private static void onLanguageChosen(Integer userId, Integer chatId, Integer messageId, String language) { + String languageCode = LocalisationService.getInstance().getLanguageCodeByName(language); + DatabaseManager.getInstance().putUserWeatherLanguageOption(userId, languageCode); + + SendMessage sendMessageRequest = new SendMessage(); + sendMessageRequest.setChatId(chatId); + sendMessageRequest.setText(LocalisationService.getInstance().getString("languageUpdated", languageCode)); + sendMessageRequest.setReplayToMessageId(messageId); + sendMessageRequest.setReplayMarkup(getMainMenuKeyboard(languageCode)); + sendBuiltMessage(sendMessageRequest); + + DatabaseManager.getInstance().insertWeatherState(userId, chatId, MAINMENU); + } + + // endregion Language Menu Option selected + + // region Forecast Weather Menu Option selected + + private static void messageOnForecastWeather(Message message, String language, int state) { + switch(state) { + case FORECASTWEATHER: + onForecastWeather(message, language); + break; + case FORECASTNEWWEATHER: + onForecastNewWeather(message, language); + break; + case FORECASTLOCATIONWEATHER: + onForecastWeatherLocation(message, language); + break; + } + } + + private static void onForecastWeather(Message message, String language) { + if (message.hasText()) { + if (message.getText().startsWith(getNewCommand(language))) { + onNewForecastWeatherCommand(message.getChatId(), message.getFrom().getId(), message.getMessageId(), language); + } else if (message.getText().startsWith(getLocationCommand(language))) { + onLocationForecastWeatherCommand(message.getChatId(), message.getFrom().getId(), message.getMessageId(), language); + } else if (message.getText().startsWith(getCancelCommand(language))) { + onCancelCommand(message.getChatId(), message.getFrom().getId(), message.getMessageId(), + getMainMenuKeyboard(language), language); + } else { + onForecastWeatherCityReceived(message.getChatId(), message.getFrom().getId(), message.getMessageId(), + message.getText(), language); + } + } + } + + private static void onForecastNewWeather(Message message, String language) { + if (message.isReply()) { + onForecastWeatherReceived(message.getChatId(), message.getFrom().getId(), message.getMessageId(), message.getText(), language); + } else { + sendMessageDefault(message, language); + } + } + + private static void onForecastWeatherCityReceived(Integer chatId, Integer userId, Integer messageId, String text, String language) { + Integer cityId = DatabaseManager.getInstance().getRecentWeatherIdByCity(userId, text); + if (cityId != null) { + String unitsSystem = DatabaseManager.getInstance().getUserWeatherOptions(userId)[1]; + String weather = WeatherService.getInstance().fetchWeatherForecast(cityId.toString(), userId, language, unitsSystem); + SendMessage sendMessageRequest = new SendMessage(); + sendMessageRequest.setReplayMarkup(getMainMenuKeyboard(language)); + sendMessageRequest.setReplayToMessageId(messageId); + sendMessageRequest.setText(weather); + sendMessageRequest.setChatId(chatId); + sendBuiltMessage(sendMessageRequest); + DatabaseManager.getInstance().insertWeatherState(userId, chatId, MAINMENU); + } else { + sendChooseOptionMessage(chatId, messageId, getRecentsKeyboard(userId, language), language); + } + } + + private static void onLocationForecastWeatherCommand(Integer chatId, Integer userId, Integer messageId, String language) { + ForceReplyKeyboard forceReplyKeyboard = getForceReply(); + + SendMessage sendMessage = new SendMessage(); + sendMessage.setChatId(chatId); + sendMessage.setReplayToMessageId(messageId); + sendMessage.setReplayMarkup(forceReplyKeyboard); + sendMessage.setText(LocalisationService.getInstance().getString("onWeatherLocationCommand", language)); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(userId, chatId, FORECASTLOCATIONWEATHER); + } + + private static void onNewForecastWeatherCommand(Integer chatId, Integer userId, Integer messageId, String language) { + ForceReplyKeyboard forceReplyKeyboard = getForceReply(); + + SendMessage sendMessage = new SendMessage(); + sendMessage.setChatId(chatId); + sendMessage.setReplayToMessageId(messageId); + sendMessage.setReplayMarkup(forceReplyKeyboard); + sendMessage.setText(LocalisationService.getInstance().getString("onWeatherNewCommand", language)); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(userId, chatId, FORECASTNEWWEATHER); + } + + private static void onForecastWeatherLocation(Message message, String language) { + if (message.isReply() && message.hasLocation()) { + onForecastWeatherLocationReceived(message, language); + } else { + sendMessageDefault(message, language); } } + + // endregion Forecast Weather Menu Option selected + + // region Current Weather Menu Option selected + + private static void messageOnCurrentWeather(Message message, String language, int state) { + switch(state) { + case CURRENTWEATHER: + onCurrentWeather(message, language); + break; + case CURRENTNEWWEATHER: + onCurrentNewWeather(message, language); + break; + case CURRENTLOCATIONWEATHER: + onCurrentWeatherLocation(message, language); + break; + } + } + + private static void onCurrentWeather(Message message, String language) { + if (message.hasText()) { + if (message.getText().startsWith(getNewCommand(language))) { + onNewCurrentWeatherCommand(message.getChatId(), message.getFrom().getId(), message.getMessageId(), language); + } else if (message.getText().startsWith(getLocationCommand(language))) { + onLocationCurrentWeatherCommand(message.getChatId(), message.getFrom().getId(), message.getMessageId(), language); + } else if (message.getText().startsWith(getCancelCommand(language))) { + onCancelCommand(message.getChatId(), message.getFrom().getId(), message.getMessageId(), + getMainMenuKeyboard(language), language); + } else { + onCurrentWeatherCityReceived(message.getChatId(), message.getFrom().getId(), message.getMessageId(), + message.getText(), language); + } + } + } + + private static void onCurrentNewWeather(Message message, String language) { + if (message.isReply()) { + onCurrentWeatherReceived(message.getChatId(), message.getFrom().getId(), message.getMessageId(), message.getText(), language); + } else { + sendMessageDefault(message, language); + } + } + + private static void onCurrentWeatherCityReceived(Integer chatId, Integer userId, Integer messageId, String text, String language) { + Integer cityId = DatabaseManager.getInstance().getRecentWeatherIdByCity(userId, text); + if (cityId != null) { + String unitsSystem = DatabaseManager.getInstance().getUserWeatherOptions(userId)[1]; + String weather = WeatherService.getInstance().fetchWeatherCurrent(cityId.toString(), userId, language, unitsSystem); + SendMessage sendMessageRequest = new SendMessage(); + sendMessageRequest.setReplayMarkup(getMainMenuKeyboard(language)); + sendMessageRequest.setReplayToMessageId(messageId); + sendMessageRequest.setText(weather); + sendMessageRequest.setChatId(chatId); + sendBuiltMessage(sendMessageRequest); + DatabaseManager.getInstance().insertWeatherState(userId, chatId, MAINMENU); + } else { + sendChooseOptionMessage(chatId, messageId, getRecentsKeyboard(userId, language), language); + } + } + + private static void onLocationCurrentWeatherCommand(Integer chatId, Integer userId, Integer messageId, String language) { + ForceReplyKeyboard forceReplyKeyboard = getForceReply(); + + SendMessage sendMessage = new SendMessage(); + sendMessage.setChatId(chatId); + sendMessage.setReplayToMessageId(messageId); + sendMessage.setReplayMarkup(forceReplyKeyboard); + sendMessage.setText(LocalisationService.getInstance().getString("onWeatherLocationCommand", language)); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(userId, chatId, CURRENTLOCATIONWEATHER); + } + + private static void onNewCurrentWeatherCommand(Integer chatId, Integer userId, Integer messageId, String language) { + ForceReplyKeyboard forceReplyKeyboard = getForceReply(); + + SendMessage sendMessage = new SendMessage(); + sendMessage.setChatId(chatId); + sendMessage.setReplayToMessageId(messageId); + sendMessage.setReplayMarkup(forceReplyKeyboard); + sendMessage.setText(LocalisationService.getInstance().getString("onWeatherNewCommand", language)); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(userId, chatId, CURRENTNEWWEATHER); + } + + private static void onCurrentWeatherLocation(Message message, String language) { + if (message.isReply() && message.hasLocation()) { + onCurrentWeatherLocationReceived(message, language); + } else { + sendMessageDefault(message, language); + } + } + + // endregion Current Weather Menu Option selected + + // region Main menu options selected + + private static void messageOnMainMenu(Message message, String language) { + if (message.hasText()) { + if (message.getText().equals(getCurrentCommand(language))) { + onCurrentChoosen(message, language); + } else if (message.getText().equals(getForecastCommand(language))) { + onForecastChoosen(message, language); + } else if (message.getText().equals(getSettingsCommand(language))) { + onSettingsChoosen(message, language); + } else if (message.getText().equals(getRateCommand(language))) { + sendRateMessage(message.getChatId(), message.getMessageId(), null, language); + } else { + sendChooseOptionMessage(message.getChatId(), message.getMessageId(), + getMainMenuKeyboard(language), language); + } + } else { + sendChooseOptionMessage(message.getChatId(), message.getMessageId(), + getMainMenuKeyboard(language), language); + } + } + + private static void onSettingsChoosen(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + + ReplyKeyboardMarkup replyKeyboardMarkup = getSettingsKeyboard(language); + sendMessage.setReplayMarkup(replyKeyboardMarkup); + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setChatId(message.getChatId()); + sendMessage.setText(getSettingsMessage(language)); + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), SETTINGS); + } + + private static void onForecastChoosen(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + + ReplyKeyboardMarkup replyKeyboardMarkup = getRecentsKeyboard(message.getFrom().getId(), language); + sendMessage.setReplayMarkup(replyKeyboardMarkup); + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setChatId(message.getChatId()); + if (replyKeyboardMarkup.getKeyboard().size() > 3) { + sendMessage.setText(LocalisationService.getInstance().getString("onForecastCommandFromHistory", language)); + } else { + sendMessage.setText(LocalisationService.getInstance().getString("onForecastCommandWithoutHistory", language)); + } + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), FORECASTWEATHER); + } + + private static void onCurrentChoosen(Message message, String language) { + SendMessage sendMessage = new SendMessage(); + + ReplyKeyboardMarkup replyKeyboardMarkup = getRecentsKeyboard(message.getFrom().getId(), language); + sendMessage.setReplayMarkup(replyKeyboardMarkup); + sendMessage.setReplayToMessageId(message.getMessageId()); + sendMessage.setChatId(message.getChatId()); + if (replyKeyboardMarkup.getKeyboard().size() > 3) { + sendMessage.setText(LocalisationService.getInstance().getString("onCurrentCommandFromHistory", language)); + } else { + sendMessage.setText(LocalisationService.getInstance().getString("onCurrentCommandWithoutHistory", language)); + } + + sendBuiltMessage(sendMessage); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), CURRENTWEATHER); + } + + // endregion Main menu options selected + + // region Get Messages + + private static String getSettingsMessage(String language) { + String baseString = LocalisationService.getInstance().getString("onSettingsCommand", language); + return String.format(baseString, Emoji.GLOBE_WITH_MERIDIANS.toString(), + Emoji.STRAIGHT_RULER.toString(), Emoji.ALARM_CLOCK.toString(), + Emoji.BACK_WITH_LEFTWARDS_ARROW_ABOVE.toString()); + } + + private static String getHelpMessage(String language) { + String baseString = LocalisationService.getInstance().getString("helpWeatherMessage", language); + return String.format(baseString, Emoji.BLACK_RIGHT_POINTING_TRIANGLE.toString(), + Emoji.BLACK_RIGHT_POINTING_DOUBLE_TRIANGLE.toString(), Emoji.ALARM_CLOCK.toString(), + Emoji.EARTH_GLOBE_EUROPE_AFRICA.toString(), Emoji.STRAIGHT_RULER.toString()); + } + + private static String getLanguageMessage(String language) { + String baseString = LocalisationService.getInstance().getString("selectLanguage", language); + return String.format(baseString, language); + } + + private static String getUnitsMessage(Integer userId, String language) { + String baseString = LocalisationService.getInstance().getString("selectUnits", language); + return String.format(baseString, DatabaseManager.getInstance().getUserWeatherOptions(userId)[1]); + } + + private static String getChooseNewAlertSetMessage(String city, String language) { + String baseString = LocalisationService.getInstance().getString("newAlertSaved", language); + return String.format(baseString, Emoji.THUMBS_UP_SIGN.toString(), city); + } + + private static String getAlertListMessage(int userId, String language) { + String alertListMessage; + + List alertCities = DatabaseManager.getInstance().getAlertCitiesNameByUser(userId); + if (alertCities.size() > 0) { + String baseAlertListString = LocalisationService.getInstance().getString("initialAlertList", language); + String partialAlertListString = LocalisationService.getInstance().getString("partialAlertList", language); + String fullListOfAlerts = ""; + for (String alertCity : alertCities) { + fullListOfAlerts += String.format(partialAlertListString, Emoji.ALARM_CLOCK.toString(), alertCity); + } + alertListMessage = String.format(baseAlertListString, alertCities.size(), fullListOfAlerts); + } else { + alertListMessage = LocalisationService.getInstance().getString("noAlertList", language); + } + + return alertListMessage; + } + + + // endregion Get Messages + + // region ReplyKeyboards + + private static ReplyKeyboardMarkup getMainMenuKeyboard(String language) { + ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup(); + replyKeyboardMarkup.setSelective(true); + replyKeyboardMarkup.setResizeKeyboard(true); + replyKeyboardMarkup.setOneTimeKeyboad(false); + + List> keyboard = new ArrayList<>(); + List keyboardFirstRow = new ArrayList<>(); + keyboardFirstRow.add(getCurrentCommand(language)); + keyboardFirstRow.add(getForecastCommand(language)); + List keyboardSecondRow = new ArrayList<>(); + keyboardSecondRow.add(getSettingsCommand(language)); + keyboardSecondRow.add(getRateCommand(language)); + keyboard.add(keyboardFirstRow); + keyboard.add(keyboardSecondRow); + replyKeyboardMarkup.setKeyboard(keyboard); + + return replyKeyboardMarkup; + } + + private static ReplyKeyboardMarkup getLanguagesKeyboard(String language) { + ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup(); + replyKeyboardMarkup.setSelective(true); + replyKeyboardMarkup.setResizeKeyboard(true); + replyKeyboardMarkup.setOneTimeKeyboad(false); + + List> keyboard = new ArrayList<>(); + for (String languageName : LocalisationService.getInstance().getSupportedLanguages().values()) { + List row = new ArrayList<>(); + row.add(languageName); + keyboard.add(row); + } + + List row = new ArrayList<>(); + row.add(getCancelCommand(language)); + keyboard.add(row); + replyKeyboardMarkup.setKeyboard(keyboard); + + return replyKeyboardMarkup; + } + + private static ReplyKeyboardMarkup getUnitsKeyboard(String language) { + ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup(); + replyKeyboardMarkup.setSelective(true); + replyKeyboardMarkup.setResizeKeyboard(true); + replyKeyboardMarkup.setOneTimeKeyboad(false); + + List> keyboard = new ArrayList<>(); + List row = new ArrayList<>(); + row.add(LocalisationService.getInstance().getString("metricSystem", language)); + keyboard.add(row); + row = new ArrayList<>(); + row.add(LocalisationService.getInstance().getString("imperialSystem", language)); + keyboard.add(row); + row = new ArrayList<>(); + row.add(getCancelCommand(language)); + keyboard.add(row); + replyKeyboardMarkup.setKeyboard(keyboard); + + return replyKeyboardMarkup; + } + + private static ReplyKeyboardMarkup getSettingsKeyboard(String language) { + ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup(); + replyKeyboardMarkup.setSelective(true); + replyKeyboardMarkup.setResizeKeyboard(true); + replyKeyboardMarkup.setOneTimeKeyboad(false); + + List> keyboard = new ArrayList<>(); + List keyboardFirstRow = new ArrayList<>(); + keyboardFirstRow.add(getLanguagesCommand(language)); + keyboardFirstRow.add(getUnitsCommand(language)); + List keyboardSecondRow = new ArrayList<>(); + keyboardSecondRow.add(getAlertsCommand(language)); + keyboardSecondRow.add(getBackCommand(language)); + keyboard.add(keyboardFirstRow); + keyboard.add(keyboardSecondRow); + replyKeyboardMarkup.setKeyboard(keyboard); + + return replyKeyboardMarkup; + } + + private static ReplyKeyboardMarkup getRecentsKeyboard(Integer userId, String language) { + return getRecentsKeyboard(userId, language, true); + } + + private static ReplyKeyboardMarkup getRecentsKeyboard(Integer userId, String language, boolean allowNew) { + ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup(); + replyKeyboardMarkup.setSelective(true); + replyKeyboardMarkup.setResizeKeyboard(true); + replyKeyboardMarkup.setOneTimeKeyboad(true); + + List> keyboard = new ArrayList<>(); + for (String recentWeather : DatabaseManager.getInstance().getRecentWeather(userId)) { + List row = new ArrayList<>(); + row.add(recentWeather); + keyboard.add(row); + } + + List row = new ArrayList<>(); + if (allowNew) { + row.add(getLocationCommand(language)); + keyboard.add(row); + + row = new ArrayList<>(); + row.add(getNewCommand(language)); + keyboard.add(row); + + row = new ArrayList<>(); + } + row.add(getCancelCommand(language)); + keyboard.add(row); + + replyKeyboardMarkup.setKeyboard(keyboard); + + return replyKeyboardMarkup; + } + + private static ReplyKeyboardMarkup getAlertsKeyboard(String language) { + ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup(); + replyKeyboardMarkup.setSelective(true); + replyKeyboardMarkup.setResizeKeyboard(true); + replyKeyboardMarkup.setOneTimeKeyboad(true); + + List> keyboard = new ArrayList<>(); + + List row = new ArrayList<>(); + row.add(getNewCommand(language)); + row.add(getDeleteCommand(language)); + keyboard.add(row); + + row = new ArrayList<>(); + row.add(getListCommand(language)); + row.add(getBackCommand(language)); + keyboard.add(row); + + replyKeyboardMarkup.setKeyboard(keyboard); + + return replyKeyboardMarkup; + } + + private static ReplyKeyboardMarkup getAlertsListKeyboard(Integer userId, String language) { + ReplyKeyboardMarkup replyKeyboardMarkup = null; + + List alertCitiesNames = DatabaseManager.getInstance().getAlertCitiesNameByUser(userId); + if (alertCitiesNames.size() > 0) { + replyKeyboardMarkup = new ReplyKeyboardMarkup(); + replyKeyboardMarkup.setSelective(true); + replyKeyboardMarkup.setResizeKeyboard(true); + replyKeyboardMarkup.setOneTimeKeyboad(true); + + List> keyboard = new ArrayList<>(); + for (String alertCityName: alertCitiesNames) { + List row = new ArrayList<>(); + row.add(alertCityName); + keyboard.add(row); + } + List row = new ArrayList<>(); + row.add(getCancelCommand(language)); + keyboard.add(row); + + replyKeyboardMarkup.setKeyboard(keyboard); + } + + return replyKeyboardMarkup; + } + + private static ForceReplyKeyboard getForceReply() { + ForceReplyKeyboard forceReplyKeyboard = new ForceReplyKeyboard(); + forceReplyKeyboard.setForceReply(true); + forceReplyKeyboard.setSelective(true); + return forceReplyKeyboard; + } + + // endregion ReplyKeyboards + + // region getCommnads + + private static String getRateCommand(String language) { + return String.format(LocalisationService.getInstance().getString("rateMe", language), + Emoji.HUNDRED_POINTS_SYMBOL.toString()); + } + + private static String getListCommand(String language) { + return String.format(LocalisationService.getInstance().getString("showList", language), + Emoji.CLIPBOARD.toString()); + } + + private static String getDeleteCommand(String language) { + return String.format(LocalisationService.getInstance().getString("delete", language), + Emoji.HEAVY_MINUS_SIGN.toString()); + } + + private static String getLanguagesCommand(String language) { + return String.format(LocalisationService.getInstance().getString("languages", language), + Emoji.GLOBE_WITH_MERIDIANS.toString()); + } + + private static String getUnitsCommand(String language) { + return String.format(LocalisationService.getInstance().getString("units", language), + Emoji.STRAIGHT_RULER.toString()); + } + + private static String getAlertsCommand(String language) { + return String.format(LocalisationService.getInstance().getString("alerts", language), + Emoji.ALARM_CLOCK.toString()); + } + + private static String getBackCommand(String language) { + return String.format(LocalisationService.getInstance().getString("back", language), + Emoji.BACK_WITH_LEFTWARDS_ARROW_ABOVE.toString()); + } + + private static String getNewCommand(String language) { + return String.format(LocalisationService.getInstance().getString("new", language), + Emoji.HEAVY_PLUS_SIGN.toString()); + } + + private static String getLocationCommand(String language) { + return String.format(LocalisationService.getInstance().getString("location", language), + Emoji.ROUND_PUSHPIN.toString()); + } + + private static String getSettingsCommand(String language) { + return String.format(LocalisationService.getInstance().getString("settings", language), + Emoji.WRENCH.toString()); + } + + private static String getCurrentCommand(String language) { + return String.format(LocalisationService.getInstance().getString("current", language), + Emoji.BLACK_RIGHT_POINTING_TRIANGLE.toString()); + } + + private static String getHelpCommand(String language) { + return String.format(LocalisationService.getInstance().getString("help", language), + Emoji.BLACK_QUESTION_MARK_ORNAMENT.toString()); + } + + private static String getForecastCommand(String language) { + return String.format(LocalisationService.getInstance().getString("forecast", language), + Emoji.BLACK_RIGHT_POINTING_DOUBLE_TRIANGLE.toString()); + } + + private static String getCancelCommand(String language) { + return String.format(LocalisationService.getInstance().getString("cancel", language), + Emoji.CROSS_MARK.toString()); + } + // endregion getCommnads + + // region Send common messages + + private static void sendMessageDefault(Message message, String language) { + ReplyKeyboardMarkup replyKeyboardMarkup = getMainMenuKeyboard(language); + sendHelpMessage(message.getChatId(), message.getMessageId(), replyKeyboardMarkup, language); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), MAINMENU); + } + + private static void sendChooseOptionMessage(Integer chatId, Integer messageId, + ReplyKeyboard replyKeyboard, String language) { + SendMessage sendMessage = new SendMessage(); + sendMessage.setChatId(chatId); + sendMessage.setReplayToMessageId(messageId); + sendMessage.setReplayMarkup(replyKeyboard); + sendMessage.setText(LocalisationService.getInstance().getString("chooseOption", language)); + sendBuiltMessage(sendMessage); + } + + private static void sendHelpMessage(Integer chatId, Integer messageId, ReplyKeyboardMarkup replyKeyboardMarkup, String language) { + SendMessage sendMessage = new SendMessage(); + sendMessage.setChatId(chatId); + sendMessage.setReplayToMessageId(messageId); + if (replyKeyboardMarkup != null) { + sendMessage.setReplayMarkup(replyKeyboardMarkup); + } + sendMessage.setText(getHelpMessage(language)); + sendBuiltMessage(sendMessage); + } + + private static void sendRateMessage(Integer chatId, Integer messageId, ReplyKeyboardMarkup replyKeyboardMarkup, String language) { + SendMessage sendMessage = new SendMessage(); + sendMessage.setChatId(chatId); + sendMessage.setReplayToMessageId(messageId); + if (replyKeyboardMarkup != null) { + sendMessage.setReplayMarkup(replyKeyboardMarkup); + } + sendMessage.setText(LocalisationService.getInstance().getString("rateMeMessage", language)); + sendBuiltMessage(sendMessage); + } + + // endregion Send common messages + + // region Send weather + + private static void onForecastWeatherLocationReceived(Message message, String language) { + String unitsSystem = DatabaseManager.getInstance().getUserWeatherOptions(message.getFrom().getId())[1]; + String weather = WeatherService.getInstance().fetchWeatherForecastByLocation(message.getLocation().getLongitude(), + message.getLocation().getLatitude(), message.getFrom().getId(), language, unitsSystem); + SendMessage sendMessageRequest = new SendMessage(); + sendMessageRequest.setReplayMarkup(getMainMenuKeyboard(language)); + sendMessageRequest.setReplayToMessageId(message.getMessageId()); + sendMessageRequest.setText(weather); + sendMessageRequest.setChatId(message.getChatId()); + sendBuiltMessage(sendMessageRequest); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), MAINMENU); + } + + private static void onForecastWeatherReceived(Integer chatId, Integer userId, Integer messageId, String text, String language) { + String unitsSystem = DatabaseManager.getInstance().getUserWeatherOptions(userId)[1]; + String weather = WeatherService.getInstance().fetchWeatherForecast(text, userId, language, unitsSystem); + SendMessage sendMessageRequest = new SendMessage(); + sendMessageRequest.setReplayMarkup(getMainMenuKeyboard(language)); + sendMessageRequest.setReplayToMessageId(messageId); + sendMessageRequest.setText(weather); + sendMessageRequest.setChatId(chatId); + sendBuiltMessage(sendMessageRequest); + DatabaseManager.getInstance().insertWeatherState(userId, chatId, MAINMENU); + } + + private static void onCurrentWeatherLocationReceived(Message message, String language) { + String unitsSystem = DatabaseManager.getInstance().getUserWeatherOptions(message.getFrom().getId())[1]; + String weather = WeatherService.getInstance().fetchWeatherCurrentByLocation(message.getLocation().getLongitude(), + message.getLocation().getLatitude(), message.getFrom().getId(), language, unitsSystem); + SendMessage sendMessageRequest = new SendMessage(); + sendMessageRequest.setReplayMarkup(getMainMenuKeyboard(language)); + sendMessageRequest.setReplayToMessageId(message.getMessageId()); + sendMessageRequest.setText(weather); + sendMessageRequest.setChatId(message.getChatId()); + sendBuiltMessage(sendMessageRequest); + DatabaseManager.getInstance().insertWeatherState(message.getFrom().getId(), message.getChatId(), MAINMENU); + } + + private static void onCurrentWeatherReceived(Integer chatId, Integer userId, Integer messageId, String text, String language) { + String unitsSystem = DatabaseManager.getInstance().getUserWeatherOptions(userId)[1]; + String weather = WeatherService.getInstance().fetchWeatherCurrent(text, userId, language, unitsSystem); + SendMessage sendMessageRequest = new SendMessage(); + sendMessageRequest.setReplayMarkup(getMainMenuKeyboard(language)); + sendMessageRequest.setReplayToMessageId(messageId); + sendMessageRequest.setText(weather); + sendMessageRequest.setChatId(chatId); + sendBuiltMessage(sendMessageRequest); + DatabaseManager.getInstance().insertWeatherState(userId, chatId, MAINMENU); + } + + // endregion Send weather + + // region Helper Methods + + private static void sendBuiltMessage(SendMessage sendMessage) { + SenderHelper.SendMessage(sendMessage, TOKEN); + } + + // endregion Helper Methods } diff --git a/src/main/java/org/telegram/updatesreceivers/UpdatesThread.java b/src/main/java/org/telegram/updatesreceivers/UpdatesThread.java index 348225c..3baba0c 100644 --- a/src/main/java/org/telegram/updatesreceivers/UpdatesThread.java +++ b/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 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 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 updates = new ArrayList(); 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); } } } diff --git a/src/main/java/org/telegram/updatesreceivers/Webhook.java b/src/main/java/org/telegram/updatesreceivers/Webhook.java index 3a4d974..6f31abc 100644 --- a/src/main/java/org/telegram/updatesreceivers/Webhook.java +++ b/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); } } diff --git a/src/main/resources/localisation/strings.properties b/src/main/resources/localisation/strings.properties new file mode 100644 index 0000000..ee3d874 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/src/main/resources/localisation/strings_es.properties b/src/main/resources/localisation/strings_es.properties new file mode 100644 index 0000000..dfd90c3 --- /dev/null +++ b/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 diff --git a/src/main/resources/localisation/strings_nl.properties b/src/main/resources/localisation/strings_nl.properties new file mode 100644 index 0000000..c7e517b --- /dev/null +++ b/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 diff --git a/src/main/resources/localisation/strings_pt.properties b/src/main/resources/localisation/strings_pt.properties new file mode 100644 index 0000000..09efd99 --- /dev/null +++ b/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