├── .gitignore
├── CODEOWNERS
├── LICENSE
├── Procfile
├── README.md
├── pom.xml
├── src
└── main
│ ├── java
│ └── com
│ │ └── companerobot
│ │ ├── CompaneroBot.java
│ │ ├── Main.java
│ │ ├── constants
│ │ ├── Callbacks.java
│ │ ├── ExecutionConstants.java
│ │ ├── HookMessages.java
│ │ ├── InlineButtonNames.java
│ │ ├── Locales.java
│ │ ├── TextMessages.java
│ │ ├── TextValues.java
│ │ └── URLs.java
│ │ ├── enums
│ │ ├── CountryCode.java
│ │ ├── DriverInfoFillingStatus.java
│ │ ├── OrderStatus.java
│ │ ├── OrderType.java
│ │ ├── UserRole.java
│ │ └── UserStatus.java
│ │ ├── helpers
│ │ ├── AddressHelper.java
│ │ ├── CipherHelper.java
│ │ ├── CyrillicStringHelper.java
│ │ ├── LocalizationHelper.java
│ │ ├── MessageExecutionHelper.java
│ │ ├── PriceCalculatingHelper.java
│ │ ├── PriceHelper.java
│ │ ├── RestrictionHelper.java
│ │ └── RoutingHelper.java
│ │ ├── keyboards
│ │ ├── InlineKeyboardHelper.java
│ │ ├── ReplyKeyboardHelper.java
│ │ └── UserManagementReplyKeyboards.java
│ │ ├── misc
│ │ ├── DriverCollection.java
│ │ ├── MongoBaseClass.java
│ │ ├── OrderCollection.java
│ │ ├── RestrictedAreasCollection.java
│ │ ├── ReviewCollection.java
│ │ └── UserCollection.java
│ │ └── parsers
│ │ ├── CommandParser.java
│ │ ├── ContactParser.java
│ │ ├── LocationParser.java
│ │ ├── MessageParser.java
│ │ ├── QueryParser.java
│ │ ├── location_parsers
│ │ ├── DriverLocationParser.java
│ │ └── PassengerLocationParser.java
│ │ ├── message_parsers
│ │ ├── DriverMessageParser.java
│ │ ├── MiscMessageParser.java
│ │ └── PassengerMessageParser.java
│ │ └── query_parsers
│ │ ├── DriverQueryParser.java
│ │ └── PassengerQueryParser.java
│ └── resources
│ ├── execution.properties
│ ├── localization_de_DE.properties
│ ├── localization_en_US.properties
│ ├── localization_es_ES.properties
│ ├── localization_fr_FR.properties
│ ├── localization_pt_PT.properties
│ └── localization_uk_UA.properties
└── system.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | .gradle
3 | .idea
4 | target
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # This is a CODEOWNERS file for GitHub
2 | # It specifies who has the ability to review and approve changes to files in the repository
3 |
4 | # Full access for all files in the repository:
5 | * @kopytovskiy
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | worker: java -Dbot_token=$BOT_TOKEN -Dmongodb_client_url=$MONGODB_CLIENT_URL -Dcipher_algorithm=$CIPHER_ALGORITHM -Dcipher_key=$CIPHER_KEY -Dserver.port=$PORT $JAVA_OPTS -jar target/*.jar
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |

2 |
3 |
4 | Compañero is an open-source ridesharing and hitchhiking service. Find a travel companion without any expenses!
5 |
6 | POC: https://t.me/CompaneroBot
7 |
8 | Website | Public Channel | Chat
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ## Table of Contents
19 | - [Features](#features)
20 | - [How It Works](#how-it-works)
21 | - [Getting started](#getting-started)
22 | - [Our Philosophy](#our-philosophy)
23 | - [Contributing](#contributing)
24 | - [Sponsorship](#sponsorship)
25 | - [License](#license)
26 |
27 | ## Features
28 | * **Privacy**. No personal data needed to use our app.
29 | * **Multi-language**. For now, we support 6 languages: English, Spanish, Ukrainian, Portuguese, French, German.
30 | * **Free**. Compañero is completely free and open-source.
31 | * **Cross-plarform**. Use it on any device where Telegram is installed.
32 | * **Simplicity**. Request a ride just in several clicks and all drivers near-by will recieve it.
33 | * **Price calculation**. You can always rely on our price calculations or set your own price, even request a free ride!
34 | * **Rating system**. Rate drivers and passengers after each ride, fostering trust and safety within our community.
35 |
36 | ## How It Works
37 | 1. You set up a profile and choose a role (driver or passenger).
38 | 2. As a passenger, you can request a ride by sending the location of the pickup point and the destination point.
39 | 3. Also, as a passenger, you can provide extra information, set a price (we also calculate a recommended one for you 🥰), and choose a pickup time.
40 | 4. If you request a ride for now, all drivers in an area of **25 kilometers** around you will receive your request.
41 | 5. If you request a ride for later, all drivers in the area of **125 kilometers** around you will receive your request.
42 | 6. As a driver, you can see the pickup point, the approximate destination point, the price, and some extra information (**not personal data**).
43 | 7. You can accept this ride request and see the user's contacts that he provided. At the pickup point, you will see the full destination address.
44 |
45 | ## Getting started
46 | 1. Generate Telegram Token, using [@BotFather](https://t.me/BotFather).
47 | 2. Run your [MongoDB](https://github.com/mongodb/mongo) database.
48 | 3. Create "CompaneroBotDB" database in your MondoDB. (optional step)
49 | 4. Create collection "driversInfo" in your "CompaneroBotDB" database. (optional step)
50 | 5. Create "2dsphere" index for "location" field in "driversInfo" collection.
51 | 6. Run Compañero using next command: `mvn clean compile exec:java -Dexec.mainClass=com.companerobot.Main -Dbot_token=*token* -Dmongodb_client_url=*url* -Dcipher_algorithm=*algorithm* -Dcipher_key=*key*`
52 | * For `-Dcipher_algorithm` you can use "AES/ECB/PKCS5Padding" or any alternative to it.
53 | 7. Have fun 😉
54 |
55 | ## Our Philosophy
56 | 1. We believe in kindness and the power of human connection.
57 | 2. We believe that travel should be accessible to all, regardless of economic status.
58 | 3. We believe in environmentally conscious travelling approach and one of our aims is to reduce carbon footprints.
59 | 4. We believe that simplicity is a key.
60 |
61 | ## Contributing
62 | We welcome contributions to our project! Here are some ways you can help:
63 | * 🐛 Report bugs or suggest features
64 | * 💻 Submit pull requests
65 | * 🙋♂️ Vote for new features in our [public channel](https://t.me/CompaneroUpdates)
66 | * 🔍 Perform code reviews
67 | * 📖 Improve documentation
68 | * 🧪 Add or improve tests
69 | * 🌐 Help with translations
70 | * 🤝 Provide support in discussions
71 | * 🚀 Share the project
72 | * ⭐ Star us on GitHub — it motivates us a lot!
73 |
74 | A huge thank you to everyone who is helping to improve Compañero. Thanks to you, the project can evolve!
75 |
76 | ### Our Contributors
77 |
78 |
79 |
80 | ## Sponsorship
81 |
82 | I don't ask for donations for this project, but I kindly request your support for Ukraine during these tough times 🇺🇦
83 |
84 | The country and its people are facing a humanitarian disaster and need our help. If you find this project useful, please consider making a donation to reputable organizations providing aid to Ukraine. Every contribution, no matter how small, can make a significant difference.
85 |
86 | You can choose any fund you like or make a donation at [savelife.in.ua](https://savelife.in.ua/en/donate-en/).
87 |
88 | Thank you for your compassion and generosity 🙏
89 |
90 | ## License
91 |
92 | This project is licensed under the GNU Affero General Public License v3.0 - see the [LICENSE](LICENSE) file for details.
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.companerobot
8 | companero-bot
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 | GNU AFFERO GENERAL PUBLIC LICENSE, Version 3 (AGPL-3.0)
14 | https://www.gnu.org/licenses/agpl-3.0.txt
15 |
16 |
17 |
18 |
19 | Companero
20 | The best open-source alternative for having a ride
21 | https://github.com/kopytovskiy/companero-bot
22 |
23 |
24 |
25 | Maksym Kopytovskyi
26 | m.kopytovskiy@gmail.com
27 |
28 |
29 |
30 |
31 | 21
32 | 21
33 | UTF-8
34 |
35 |
36 |
37 |
38 |
39 |
40 | org.junit.jupiter
41 | junit-jupiter-api
42 | 5.9.0
43 | test
44 |
45 |
46 | org.junit.jupiter
47 | junit-jupiter-engine
48 | 5.9.0
49 | test
50 |
51 |
52 | org.junit.platform
53 | junit-platform-suite
54 | 1.9.0
55 | test
56 |
57 |
58 |
59 |
60 | org.telegram
61 | telegrambots-longpolling
62 | 7.10.0
63 |
64 |
65 | org.telegram
66 | telegrambots-client
67 | 7.10.0
68 |
69 |
70 |
71 |
72 | org.mongodb
73 | mongodb-driver-sync
74 | 5.1.0
75 |
76 |
77 |
78 |
79 | org.apache.maven.plugins
80 | maven-surefire-report-plugin
81 | 3.0.0-M7
82 |
83 |
84 |
85 |
86 | org.slf4j
87 | slf4j-simple
88 | 2.0.2
89 |
90 |
91 |
92 |
93 | org.apache.httpcomponents.client5
94 | httpclient5
95 | 5.2.1
96 |
97 |
98 |
99 |
100 | org.json
101 | json
102 | 20240303
103 |
104 |
105 |
106 |
107 | org.codehaus.mojo
108 | exec-maven-plugin
109 | 3.1.0
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 | org.apache.maven.plugins
118 | maven-site-plugin
119 | 4.0.0-M3
120 |
121 |
122 |
123 |
124 | org.apache.maven.plugins
125 | maven-assembly-plugin
126 | 3.6.0
127 |
128 |
129 |
130 | com.companerobot.Main
131 |
132 |
133 |
134 | jar-with-dependencies
135 |
136 |
137 |
138 |
139 | make-assembly
140 | package
141 |
142 | single
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | org.apache.maven.plugins
151 | maven-surefire-plugin
152 | 3.0.0-M7
153 |
154 | src/main/resources/execution.properties
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 | org.apache.maven.plugins
169 | maven-surefire-report-plugin
170 | 3.0.0-M7
171 |
172 |
173 |
174 | report-only
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/CompaneroBot.java:
--------------------------------------------------------------------------------
1 | package com.companerobot;
2 |
3 | import com.companerobot.parsers.*;
4 |
5 | import com.companerobot.parsers.MessageParser;
6 | import org.telegram.telegrambots.longpolling.util.LongPollingSingleThreadUpdateConsumer;
7 |
8 | import org.telegram.telegrambots.meta.api.objects.Update;
9 | import org.telegram.telegrambots.meta.api.objects.message.Message;
10 |
11 | public class CompaneroBot implements LongPollingSingleThreadUpdateConsumer {
12 |
13 | @Override
14 | public void consume(Update update) {
15 | if (update.hasMessage()) {
16 | Message currentMessage = update.getMessage();
17 |
18 | if (currentMessage.isCommand()) {
19 | CommandParser.parseCommand(currentMessage);
20 |
21 | } else if (currentMessage.hasLocation()) {
22 | LocationParser.parseLocation(currentMessage);
23 |
24 | } else if (currentMessage.hasContact()) {
25 | ContactParser.parseContact(currentMessage);
26 |
27 | } else {
28 | MessageParser.parseMessage(currentMessage);
29 |
30 | }
31 | } else if (update.hasCallbackQuery()) {
32 | QueryParser.parseQuery(update);
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/Main.java:
--------------------------------------------------------------------------------
1 | package com.companerobot;
2 |
3 | import org.telegram.telegrambots.longpolling.TelegramBotsLongPollingApplication;
4 |
5 | import static com.companerobot.constants.ExecutionConstants.BOT_TOKEN;
6 |
7 | public class Main {
8 |
9 | public static CompaneroBot companeroBot = new CompaneroBot();
10 | public static void main(String[] args) {
11 | System.out.println("Bot is starting...");
12 |
13 | try (TelegramBotsLongPollingApplication botsApplication = new TelegramBotsLongPollingApplication()) {
14 | botsApplication.registerBot(BOT_TOKEN, companeroBot);
15 | System.out.println("CompaneroBot successfully started!");
16 |
17 | Thread.currentThread().join();
18 | } catch (Exception e) {
19 | e.printStackTrace();
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/constants/Callbacks.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.constants;
2 |
3 | public class Callbacks {
4 |
5 | public static final String ACCEPT_ORDER_CALLBACK = "accept_order";
6 |
7 | public static final String ADD_POSTPONED_DEPARTURE_DETAILS_CALLBACK = "add_postponed_departure_details";
8 |
9 | public static final String LIKE_RIDE_CALLBACK = "like_ride";
10 |
11 | public static final String DISLIKE_RIDE_CALLBACK = "dislike_ride";
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/constants/ExecutionConstants.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.constants;
2 |
3 | public class ExecutionConstants {
4 |
5 | public static final String CIPHER_ALGORITHM = System.getProperty("cipher_algorithm");
6 |
7 | public static final String CIPHER_KEY = System.getProperty("cipher_key");
8 |
9 | public static final String BOT_TOKEN = System.getProperty("bot_token");
10 |
11 | public static final String MONGODB_CLIENT_URL = System.getProperty("mongodb_client_url");
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/constants/HookMessages.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.constants;
2 |
3 | import com.companerobot.helpers.CyrillicStringHelper;
4 |
5 | public class HookMessages {
6 |
7 | public static final String CHOOSE_ENGLISH_LANGUAGE_HOOK_MESSAGE = "\uD83C\uDDEC\uD83C\uDDE7 English";
8 |
9 | public static final String CHOOSE_SPANISH_LANGUAGE_HOOK_MESSAGE = "\uD83C\uDDEA\uD83C\uDDF8 Español";
10 |
11 | public static final String CHOOSE_UKRAINIAN_LANGUAGE_HOOK_MESSAGE = CyrillicStringHelper.getCyrillicString("\uD83C\uDDFA\uD83C\uDDE6 Українська");
12 |
13 | public static final String CHOOSE_PORTUGUESE_LANGUAGE_HOOK_MESSAGE = "\uD83C\uDDF5\uD83C\uDDF9 Portuguesa";
14 |
15 | public static final String CHOOSE_GERMAN_LANGUAGE_HOOK_MESSAGE = "\uD83C\uDDE9\uD83C\uDDEA Deutsch";
16 |
17 | public static final String CHOOSE_FRENCH_LANGUAGE_HOOK_MESSAGE = "\uD83C\uDDEB\uD83C\uDDF7 Française";
18 |
19 | public static final String AUTHORIZE_AS_PASSENGER_HOOK_MESSAGE = "authorize.as.passenger.hook.message";
20 |
21 | public static final String AUTHORIZE_AS_DRIVER_HOOK_MESSAGE = "authorize.as.driver.hook.message";
22 |
23 | public static final String CONFIRM_ARRIVAL_HOOK_MESSAGE = "confirm.arrival.hook.message";
24 |
25 | public static final String CREATE_NEW_ORDER_HOOK_MESSAGE = "create.new.order.hook.message";
26 |
27 | public static final String CANCEL_ORDER_HOOK_MESSAGE = "cancel.order.hook.message";
28 |
29 | public static final String FINISH_ORDER_HOOK_MESSAGE = "finish.order.hook.message";
30 |
31 | public static final String SHARE_LOCATION_HOOK_MESSAGE = "share.location.hook.message";
32 |
33 | public static final String UPDATE_LOCATION_HOOK_MESSAGE = "update.location.hook.message";
34 |
35 | public static final String START_WORK_SHIFT_HOOK_MESSAGE = "start.work.shift.hook.message";
36 |
37 | public static final String STOP_WORK_SHIFT_HOOK_MESSAGE = "stop.work.shift.hook.message";
38 |
39 | public static final String SHARE_MY_CONTACT_HOOK_MESSAGE = "share.my.contact.hook.message";
40 |
41 | public static final String SKIP_SHARE_MY_CONTACT_HOOK_MESSAGE = "skip.share.my.contact.hook.message";
42 |
43 | public static final String ADD_NOTES_HOOK_MESSAGE = "add.notes.hook.message";
44 |
45 | public static final String SKIP_NOTES_HOOK_MESSAGE = "skip.notes.hook.message";
46 |
47 | public static final String RECOMMENDED_PRICE_HOOK_MESSAGE = "recommended.price.hook.message";
48 |
49 | public static final String CONFIRM_ORDER_HOOK_MESSAGE = "confirm.order.hook.message";
50 |
51 | public static final String FREE_RIDE_HOOK_MESSAGE = "free.ride.hook.message";
52 |
53 | public static final String CONFIRM_POSTPONED_ORDER_HOOK_MESSAGE = "confirm.postponed.order.hook.message";
54 |
55 | public static final String DECLINE_POSTPONED_ORDER_HOOK_MESSAGE = "decline.postponed.order.hook.message";
56 |
57 |
58 | //USER MANAGEMENT
59 | public static final String OPEN_SETTINGS_HOOK_MESSAGE = "open.settings.hook.message";
60 |
61 | public static final String GET_SUPPORT_HOOK_MESSAGE = "get.support.hook.message";
62 |
63 | public static final String EXIT_SETTINGS_HOOK_MESSAGE = "exit.settings.hook.message";
64 |
65 | public static final String BACK_TO_PREVIOUS_PAGE_HOOK_MESSAGE = "back.to.previous.page.hook.message";
66 |
67 | public static final String EDIT_USER_NAME_HOOK_MESSAGE = "edit.user.name.hook.message";
68 |
69 | public static final String EDIT_PHONE_NUMBER_HOOK_MESSAGE = "edit.phone.number.hook.message";
70 |
71 | public static final String REMOVE_PHONE_NUMBER_HOOK_MESSAGE = "remove.phone.number.hook.message";
72 |
73 | public static final String EDIT_SHARE_PHONE_NUMBER_HOOK_MESSAGE = "edit.share.phone.number.hook.message";
74 |
75 | public static final String REVEAL_PHONE_NUMBER_HOOK_MESSAGE = "reveal.phone.number.hook.message";
76 |
77 | public static final String HIDE_PHONE_NUMBER_HOOK_MESSAGE = "hide.phone.number.hook.message";
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/constants/InlineButtonNames.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.constants;
2 |
3 | public class InlineButtonNames {
4 |
5 | public static final String WRITE_TO_PASSENGER_INLINE_TEXT = "write.to.passenger.inline.text";
6 |
7 | public static final String WRITE_TO_DRIVER_INLINE_TEXT = "write.to.driver.inline.text";
8 |
9 | public static final String ACCEPT_INLINE_TEXT = "accept.inline.text";
10 |
11 | public static final String OPEN_PICKUP_POINT_INLINE_TEXT = "open.pickup.point.inline.text";
12 |
13 | public static final String OPEN_DESTINATION_POINT_INLINE_TEXT = "open.destination.point.inline.text";
14 |
15 | public static final String WALLET_INLINE_TEXT = "wallet.inline.text";
16 |
17 | public static final String ADD_POSTPONED_DEPARTURE_DETAILS_INLINE_TEXT = "add.postponed.departure.details.inline.text";
18 |
19 | public static final String LIKE_RIDE_INLINE_TEXT = "\uD83D\uDC4D";
20 |
21 | public static final String DISLIKE_RIDE_INLINE_TEXT = "\uD83D\uDC4E";
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/constants/Locales.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.constants;
2 |
3 | import java.util.Locale;
4 |
5 | public class Locales {
6 |
7 | public static final Locale UA = Locale.of("uk", "UA");
8 |
9 | public static final Locale US = Locale.of("en", "US");
10 |
11 | public static final Locale ES = Locale.of("es", "ES");
12 |
13 | public static final Locale FR = Locale.of("fr", "FR");
14 |
15 | public static final Locale PT = Locale.of("pt", "PT");
16 |
17 | public static final Locale DE = Locale.of("de", "DE");
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/constants/TextMessages.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.constants;
2 |
3 | import com.companerobot.helpers.CyrillicStringHelper;
4 |
5 | public class TextMessages {
6 | public static final String WELCOME_MESSAGE = """
7 | \uD83C\uDDEC\uD83C\uDDE7:"Greetings! Before we begin, could you please tell me which language you prefer to speak?"
8 |
9 | \uD83C\uDDEA\uD83C\uDDF8:"Saludos. Antes de empezar, ¿podría decirme en qué idioma prefiere hablar?"
10 |
11 | \uD83C\uDDFA\uD83C\uDDE6:"%s"
12 |
13 | \uD83C\uDDF5\uD83C\uDDF9:"Saudações! Antes de começarmos, podem dizer-me qual a língua que preferem falar?"
14 |
15 | \uD83C\uDDE9\uD83C\uDDEA:"Seien Sie gegrüßt! Bevor wir beginnen, könnten Sie mir bitte sagen, welche Sprache Sie am liebsten sprechen?"
16 |
17 | \uD83C\uDDEB\uD83C\uDDF7:"Salutations ! Avant de commencer, pourriez-vous me dire quelle langue vous préférez parler ?"
18 | """.formatted(
19 | CyrillicStringHelper.getCyrillicString("Привітулі! Перед тим як почати, вкажи, будь ласка, якою мовою тобі зручніше спілкуватись?")
20 | );
21 |
22 |
23 | //MISC MESSAGES
24 | public static final String USER_POLICY_AGREEMENT_MESSAGE = "user.policy.agreement.message";
25 |
26 | public static final String REQUEST_CONTACTS_MESSAGE = "request.contacts.message";
27 |
28 | public static final String MESSAGE_AFTER_REGISTRATION_WITH_PHONE_NUMBER = "message.after.registration.with.phone.number";
29 |
30 | public static final String MESSAGE_AFTER_REGISTRATION_WITHOUT_PHONE_NUMBER = "message.after.registration.without.phone.number";
31 |
32 | public static final String MESSAGE_MISSING_USER_TAG_GENERAL = "message.missing.user.tag.general";
33 |
34 | public static final String MISSING_USER_TAG_WITHOUT_NUMBER_PASSENGER_WARN_MESSAGE = "missing.user.tag.without.number.passenger.warn.message";
35 |
36 | public static final String MISSING_USER_TAG_WITHOUT_NUMBER_DRIVER_WARN_MESSAGE = "missing.user.tag.without.number.driver.warn.message";
37 |
38 | public static final String FINANCIAL_OPERATIONS_WARN_MESSAGE = "financial.operations.warn.message";
39 |
40 | public static final String INCORRECT_CONTACT_MESSAGE = "incorrect.contact.message";
41 |
42 | public static final String CHOOSE_ROLE_MESSAGE = "choose.role.message";
43 |
44 | public static final String AFTER_RATE_MESSAGE = "after.rate.message";
45 |
46 | public static final String ORDER_PRICE_MESSAGE = "order.price.message";
47 |
48 | public static final String ORDER_FREE_RIDE_MESSAGE = "order.free.ride.message";
49 |
50 | public static final String PHONE_NUMBER_MESSAGE = "phone.number.message";
51 |
52 | public static final String RATING_MESSAGE = "rating.message";
53 |
54 | public static final String FURTHER_CONTACTS_POSTPONED_MESSAGE = "further.contacts.postponed.message";
55 |
56 | public static final String RESTRICTED_LOCATION_MESSAGE = "restricted.location.message";
57 |
58 | public static final String RESTRICTED_PHONE_NUMBER_MESSAGE = "restricted.phone.number.message";
59 |
60 |
61 | //PASSENGER MESSAGES
62 | public static final String PASSENGER_ROLE_WELCOME_MESSAGE = "passenger.role.welcome.message";
63 |
64 | public static final String REQUEST_PICKUP_POINT_PASSENGER_MESSAGE = "request.pickup.point.passenger.message";
65 |
66 | public static final String REQUEST_DESTINATION_POINT_PASSENGER_MESSAGE = "request.destination.point.passenger.message";
67 |
68 | public static final String ASK_IF_NOTES_NEEDED_MESSAGE = "ask.if.notes.needed.message";
69 |
70 | public static final String ADD_NOTES_MESSAGE = "add.notes.message";
71 |
72 | public static final String ADD_PRICE_ORDER_MESSAGE = "add.price.order.message";
73 |
74 | public static final String PRICE_ERROR_MORE_THAN_INT_MAX_MESSAGE = "price.error.more.than.int.max.message";
75 |
76 | public static final String PRICE_ERROR_LESS_THAN_0_MESSAGE = "price.error.less.than.0.message";
77 |
78 | public static final String PRICE_ERROR_OTHER_MESSAGE = "price.error.other.message";
79 |
80 | public static final String CONFIRMATION_PASSENGER_ORDER_BASE_MESSAGE = "confirmation.passenger.order.base.message";
81 |
82 | public static final String CONFIRMATION_REMINDER_MESSAGE = "confirmation.reminder.message";
83 |
84 | public static final String CONFIRM_ORDER_BY_PASSENGER_MESSAGE = "confirm.order.by.passenger.message";
85 |
86 | public static final String DRIVER_INFO_BASE_MESSAGE = "driver.info.base.message";
87 |
88 | public static final String DRIVER_INFO_CAR_PLATE_MESSAGE = "driver.info.car.plate.message";
89 |
90 | public static final String DRIVER_INFO_CAR_PLATE_POSTPONED_MESSAGE = "driver.info.car.plate.postponed.message";
91 |
92 | public static final String DRIVER_INFO_REVIEWS_AMOUNT_MESSAGE = "driver.info.reviews.amount.message";
93 |
94 | public static final String DRIVER_INFO_MISSING_CONTACTS_MESSAGE = "driver.info.missing.contacts.message";
95 |
96 | public static final String DRIVER_INFO_LOCATION_MESSAGE = "driver.info.location.message";
97 |
98 | public static final String DRIVER_LOCATION_MESSAGE = "driver.location.message";
99 |
100 | public static final String FURTHER_STEPS_FOR_PASSENGER_POSTPONED_MESSAGE = "further.steps.for.passenger.postponed.message";
101 |
102 | public static final String CANCEL_TRIP_BY_PASSENGER_SELF_MESSAGE = "cancel.trip.by.passenger.self.message";
103 |
104 | public static final String DRIVER_ARRIVED_PASSENGER_MESSAGE = "driver.arrived.passenger.message";
105 |
106 | public static final String FINISHED_ORDER_PASSENGER_MESSAGE = "finished.order.passenger.message";
107 |
108 | public static final String CANCEL_TRIP_BY_DRIVER_MESSAGE = "cancel.trip.by.driver.message";
109 |
110 | public static final String DECLINED_POSTPONED_TRIP_FOR_PASSENGER_MESSAGE = "declined.postponed.trip.for.passenger.message";
111 |
112 | public static final String CONFIRMED_POSTPONED_TRIP_FOR_PASSENGER_MESSAGE = "confirmed.postponed.trip.for.passenger.message";
113 |
114 | public static final String ADD_REVIEW_ON_DRIVER_FOR_PASSENGERS_MESSAGE = "add.review.on.driver.for.passengers.message";
115 |
116 | public static final String PAYMENT_REMINDER_MESSAGE = "payment.reminder.message";
117 |
118 |
119 | //DRIVER
120 | public static final String REQUEST_DRIVER_LOCATION_MESSAGE = "request.driver.location.message";
121 |
122 | public static final String UNAVAILABLE_ORDER_MESSAGE = "unavailable.order.message";
123 |
124 | public static final String HAS_ALREADY_ORDER_ERROR_MESSAGE = "has.already.order.error.message";
125 |
126 | public static final String ORDER_ID_PART_MESSAGE = "order.id.part.message";
127 |
128 | public static final String NEW_ORDER_BASE_MESSAGE = "new.order.base.message";
129 |
130 | public static final String DEPARTURE_TIME_ORDER_MESSAGE = "departure.time.order.message";
131 |
132 | public static final String CAR_MODEL_REQUEST_MESSAGE = "car.model.request.message";
133 |
134 | public static final String LOCATION_SENT_TO_PASSENGER_MESSAGE = "location.sent.to.passenger.message";
135 |
136 | public static final String PASSENGER_INFO_BASE_MESSAGE = "passenger.info.base.message";
137 |
138 | public static final String PASSENGER_INFO_REVIEWS_AMOUNT_MESSAGE = "passenger.info.reviews.amount.message";
139 |
140 | public static final String PASSENGER_INFO_MISSING_CONTACTS_MESSAGE = "passenger.info.missing.contacts.message";
141 |
142 | public static final String FURTHER_STEPS_FOR_DRIVER_POSTPONED_MESSAGE = "further.steps.for.driver.postponed.message";
143 |
144 | public static final String FUTURE_ARRIVAL_REMINDER_MESSAGE = "future.arrival.reminder.message";
145 |
146 | public static final String CANCEL_TRIP_BY_PASSENGER_MESSAGE = "cancel.trip.by.passenger.message";
147 |
148 | public static final String STOP_SHIFT_MESSAGE = "stop.shift.message";
149 |
150 | public static final String START_SHIFT_MESSAGE = "start.shift.message";
151 |
152 | public static final String CAR_COLOR_REQUEST_MESSAGE = "car.color.request.message";
153 |
154 | public static final String CAR_PLATE_NUMBER_REQUEST_MESSAGE = "car.plate.number.request.message";
155 |
156 | public static final String DRIVER_LOCATION_REQUEST_MESSAGE = "driver.location.request.message";
157 |
158 | public static final String CAR_INFO_REGISTRATION_FINISHED_MESSAGE = "car.info.registration.finished.message";
159 |
160 | public static final String DESTINATION_POINT_DRIVER_MESSAGE = "destination.point.driver.message";
161 |
162 | public static final String FUTURE_FINISH_ORDER_REMINDER_MESSAGE = "future.finish.order.reminder.message";
163 |
164 | public static final String FINISHED_ORDER_DRIVER_MESSAGE = "finished.order.driver.message";
165 |
166 | public static final String CANCEL_TRIP_BY_DRIVER_SELF_MESSAGE = "cancel.trip.by.driver.self.message";
167 |
168 | public static final String DECLINED_POSTPONED_TRIP_FOR_DRIVER_MESSAGE = "declined.postponed.trip.for.driver.message";
169 |
170 | public static final String CONFIRMED_POSTPONED_TRIP_FOR_DRIVER_MESSAGE = "confirmed.postponed.trip.for.driver.message";
171 |
172 | public static final String DEPARTURE_DETAILS_MESSAGE = "departure.details.message";
173 |
174 | public static final String ADD_REVIEW_ON_PASSENGER_FOR_DRIVERS_MESSAGE = "add.review.on.passenger.for.drivers.message";
175 |
176 |
177 | //USER MANAGEMENT
178 | public static final String SHOW_ALL_USER_DATA_MESSAGE = "show.all.user.data.message";
179 |
180 | public static final String EDIT_USER_NAME_MESSAGE = "edit.user.name.message";
181 |
182 | public static final String EDIT_PHONE_NUMBER_MESSAGE = "edit.phone.number.message";
183 |
184 | public static final String REMOVE_PHONE_NUMBER_MESSAGE = "remove.phone.number.message";
185 |
186 | public static final String HIDDEN_PHONE_NUMBER_FALSE_MESSAGE = "hidden.phone.number.false.message";
187 |
188 | public static final String HIDDEN_PHONE_NUMBER_TRUE_MESSAGE = "hidden.phone.number.true.message";
189 |
190 | public static final String SUCCESSFUL_DATA_SAVED_MESSAGE = "successful.data.saved.message";
191 |
192 | public static final String ERROR_NO_PHONE_NUMBER_MESSAGE = "error.no.phone.number.message";
193 |
194 | public static final String ERROR_DRIVER_NEED_EXIT_SETTINGS_MENU_MESSAGE = "error.driver.need.exit.settings.menu.message";
195 |
196 | public static final String GET_SUPPORT_MESSAGE = "get.support.message";
197 |
198 | }
199 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/constants/TextValues.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.constants;
2 |
3 | public class TextValues {
4 |
5 | public static final String NO_VALUE = "no.value";
6 | public static final String YES_VALUE = "yes.value";
7 | public static final String EMPTY_VALUE = "empty.value";
8 | public static final String NOW_VALUE = "now.value";
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/constants/URLs.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.constants;
2 |
3 | public class URLs {
4 |
5 | public static final String OSRM_BASE_URL = "http://router.project-osrm.org/route/";
6 |
7 | public static final String OPEN_STREET_MAP_BASE_URL = "https://nominatim.openstreetmap.org/";
8 |
9 | public static final String GOOGLE_MAPS_BASE_URL = "http://www.google.com/maps/place/";
10 |
11 | public static final String PRIVACY_POLICY_ENG_URL = "https://telegra.ph/Privacy-Policy-for-Compa%C3%B1ero-Telegram-Bot-CompaneroBot-03-31";
12 |
13 | public static final String USER_POLICY_AGREEMENT_ENG_URL = "https://telegra.ph/User-Policy-Agreement-03-31";
14 |
15 | public static final String PRIVACY_POLICY_ES_URL = "https://telegra.ph/Pol%C3%ADtica-de-Privacidad-para-el-Bot-de-Telegram-Compa%C3%B1ero-CompaneroBot-06-22";
16 |
17 | public static final String USER_POLICY_AGREEMENT_ES_URL = "https://telegra.ph/Acuerdo-de-Pol%C3%ADtica-de-Usuario-06-22";
18 |
19 | public static final String PRIVACY_POLICY_PT_URL = "https://telegra.ph/Pol%C3%ADtica-de-Privacidade-para-o-Compa%C3%B1ero-Telegram-Bot-CompaneroBot-06-22";
20 |
21 | public static final String USER_POLICY_AGREEMENT_PT_URL = "https://telegra.ph/Acordo-de-Pol%C3%ADtica-de-Utilizador-06-22-2";
22 |
23 | public static final String PRIVACY_POLICY_DE_URL = "https://telegra.ph/Datenschutzrichtlinie-f%C3%BCr-den-Compa%C3%B1ero-Telegram-Bot-CompaneroBot-06-23";
24 |
25 | public static final String USER_POLICY_AGREEMENT_DE_URL = "https://telegra.ph/Nutzungsvereinbarung-06-23";
26 |
27 | public static final String PRIVACY_POLICY_FR_URL = "https://telegra.ph/Politique-de-Confidentialit%C3%A9-pour-le-Bot-Telegram-Compa%C3%B1ero-CompaneroBot-06-22";
28 |
29 | public static final String USER_POLICY_AGREEMENT_FR_URL = "https://telegra.ph/Accord-de-Politique-dUtilisation-06-22";
30 |
31 | public static final String PRIVACY_POLICY_UA_URL = "https://telegra.ph/Pol%D1%96tika-konf%D1%96denc%D1%96jnost%D1%96-telegram-bota-Compa%C3%B1ero-CompaneroBot-03-31";
32 |
33 | public static final String USER_POLICY_AGREEMENT_UA_URL = "https://telegra.ph/Ugoda-pro-pol%D1%96tiku-koristuvacha-03-31";
34 |
35 | public static final String REVOLUT_CURRENCY_CONVERTER_URL = "https://www.revolut.com/api/quote/public/EUR";
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/enums/CountryCode.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.enums;
2 |
3 | public enum CountryCode {
4 |
5 | AF("AFN", 0.5), //Afghanistan
6 | AL("ALL", 0.7), //Albania
7 | DZ("DZD", 0.3), //Algeria
8 | AD("EUR", 1.2), //Andorra
9 | AO("AOA", 0.8), //Angola
10 | AG("XCD", 1.0), //Antigua and Barbuda
11 | AR("ARS", 0.5), //Argentina
12 | AM("AMD", 0.4), //Armenia
13 | AU("AUD", 2.0), //Australia
14 | AT("EUR", 1.8), //Austria
15 | AZ("AZN", 0.4), //Azerbaijan
16 | BS("BSD", 1.5), //Bahamas
17 | BH("BHD", 1.0), //Bahrain
18 | BD("BDT", 0.2), //Bangladesh
19 | BB("BBD", 1.7), //Barbados
20 | BY("BYN", 0.6), //Belarus
21 | BE("EUR", 2.5), //Belgium
22 | BZ("BZD", 1.0), //Belize
23 | BJ("XOF", 0.5), //Benin
24 | BT("BTN", 0.7), //Bhutan
25 | BO("BOB", 0.5), //Bolivia
26 | BA("BAM", 0.9), //Bosnia and Herzegovina
27 | BW("BWP", 0.7), //Botswana
28 | BR("BRL", 0.9), //Brazil
29 | BN("BND", 0.6), //Brunei Darussalam
30 | BG("BGN", 0.8), //Bulgaria
31 | BF("XOF", 0.7), //Burkina Faso
32 | BI("BIF", 0.7), //Burundi
33 | CV("CVE", 1.0), //Cabo Verde
34 | KH("KHR", 0.5), //Cambodia
35 | CM("XAF", 0.6), //Cameroon
36 | CA("CAD", 1.7), //Canada
37 | CF("XAF", 0.6), //Central African Republic
38 | TD("XAF", 0.6), //Chad
39 | CL("CLP", 1.2), //Chile
40 | CN("CNY", 0.3), //China
41 | CO("COP", 0.4), //Colombia
42 | KM("KMF", 1.1), //Comoros
43 | CG("XAF", 0.8), //Congo
44 | CR("CRC", 1.0), //Costa Rica
45 | HR("HRK", 1.0), //Croatia
46 | CU("CUP", 1.0), //Cuba
47 | CY("EUR", 1.2), //Cyprus
48 | CZ("CZK", 1.4), //Czech Republic
49 | DK("DKK", 3.0), //Denmark
50 | DJ("DJF", 0.7), //Djibouti
51 | DM("XCD", 1.5), //Dominica
52 | DO("DOP", 0.7), //Dominican Republic
53 | EC("USD", 1.0), //Ecuador
54 | EG("EGP", 0.2), //Egypt
55 | SV("USD", 1.0), //El Salvador
56 | GQ("XAF", 0.7), //Equatorial Guinea
57 | ER("ERN", 0.8), //Eritrea
58 | EE("EUR", 0.7), //Estonia
59 | SZ("SZL", 0.9), //Eswatini
60 | ET("ETB", 0.5), //Ethiopia
61 | FJ("FJD", 0.9), //Fiji
62 | FI("EUR", 1.9), //Finland
63 | FR("EUR", 1.7), //France
64 | GA("XAF", 0.8), //Gabon
65 | GM("GMD", 0.7), //Gambia
66 | GE("GEL", 0.3), //Georgia
67 | DE("EUR", 2.3), //Germany
68 | GH("GHS", 0.9), //Ghana
69 | GR("EUR", 1.1), //Greece
70 | GD("XCD", 1.2), //Grenada
71 | GT("GTQ", 0.8), //Guatemala
72 | GN("GNF", 0.7), //Guinea
73 | GW("XOF", 0.8), //Guinea-Bissau
74 | GY("GYD", 0.9), //Guyana
75 | HT("HTG", 1.5), //Haiti
76 | HN("HNL", 0.8), //Honduras
77 | HU("HUF", 1.1), //Hungary
78 | IS("ISK", 2.5), //Iceland
79 | IN("INR", 0.2), //India
80 | ID("IDR", 0.4), //Indonesia
81 | IR("IRR", 0.3), //Iran
82 | IQ("IQD", 0.5), //Iraq
83 | IE("EUR", 1.4), //Ireland
84 | IL("ILS", 1.5), //Israel
85 | IT("EUR", 1.9), //Italy
86 | JM("JMD", 1.2), //Jamaica
87 | JP("JPY", 3.2), //Japan
88 | JO("JOD", 0.7), //Jordan
89 | KZ("KZT", 0.6), //Kazakhstan
90 | KE("KES", 0.8), //Kenya
91 | KI("AUD", 1.3), //Kiribati
92 | KP("KPW", 0.9), //North Korea
93 | KR("KRW", 1.0), //South Korea
94 | KW("KWD", 1.2), //Kuwait
95 | KG("KGS", 0.3), //Kyrgyzstan
96 | LA("LAK", 0.6), //Laos
97 | LV("EUR", 0.7), //Latvia
98 | LB("LBP", 0.7), //Lebanon
99 | LS("LSL", 0.7), //Lesotho
100 | LR("LRD", 0.9), //Liberia
101 | LY("LYD", 0.4), //Libya
102 | LI("CHF", 3.5), //Liechtenstein
103 | LT("EUR", 0.8), //Lithuania
104 | LU("EUR", 3.0), //Luxembourg
105 | MG("MGA", 0.4), //Madagascar
106 | MW("MWK", 0.9), //Malawi
107 | MY("MYR", 0.5), //Malaysia
108 | MV("MVR", 1.1), //Maldives
109 | ML("XOF", 0.7), //Mali
110 | MT("EUR", 1.4), //Malta
111 | MH("USD", 2.0), //Marshall Islands
112 | MR("MRU", 0.8), //Mauritania
113 | MU("MUR", 0.9), //Mauritius
114 | MX("MXN", 0.8), //Mexico
115 | FM("USD", 1.2), //Micronesia
116 | MD("MDL", 0.5), //Moldova
117 | MC("EUR", 2.0), //Monaco
118 | MN("MNT", 0.5), //Mongolia
119 | ME("EUR", 0.9), //Montenegro
120 | MA("MAD", 0.8), //Morocco
121 | MZ("MZN", 0.9), //Mozambique
122 | MM("MMK", 0.5), //Myanmar
123 | NA("NAD", 0.8), //Namibia
124 | NR("AUD", 2.1), //Nauru
125 | NP("NPR", 0.4), //Nepal
126 | NL("EUR", 2.2), //Netherlands
127 | NZ("NZD", 1.9), //New Zealand
128 | NI("NIO", 0.7), //Nicaragua
129 | NE("XOF", 0.6), //Niger
130 | NG("NGN", 0.6), //Nigeria
131 | NO("NOK", 2.0), //Norway
132 | OM("OMR", 0.7), //Oman
133 | PK("PKR", 0.3), //Pakistan
134 | PW("USD", 1.3), //Palau
135 | PA("PAB", 0.8), //Panama
136 | PG("PGK", 0.9), //Papua New Guinea
137 | PY("PYG", 0.7), //Paraguay
138 | PE("PEN", 0.6), //Peru
139 | PH("PHP", 0.4), //Philippines
140 | PL("PLN", 1.0), //Poland
141 | PT("EUR", 1.0), //Portugal
142 | QA("QAR", 1.0), //Qatar
143 | RO("RON", 0.9), //Romania
144 | RU("RUB", 0.8), //Russia
145 | RW("RWF", 0.8), //Rwanda
146 | KN("XCD", 1.2), //Saint Kitts and Nevis
147 | LC("XCD", 1.2), //Saint Lucia
148 | VC("XCD", 1.2), //Saint Vincent and the Grenadines
149 | WS("WST", 1.0), //Samoa
150 | SM("EUR", 1.5), //San Marino
151 | ST("STN", 1.1), //Sao Tome and Principe
152 | SA("SAR", 0.5), //Saudi Arabia
153 | SN("XOF", 0.9), //Senegal
154 | RS("RSD", 0.8), //Serbia
155 | SC("SCR", 1.0), //Seychelles
156 | SL("SLL", 0.8), //Sierra Leone
157 | SG("SGD", 0.8), //Singapore
158 | SK("EUR", 1.0), //Slovakia
159 | SI("EUR", 1.2), //Slovenia
160 | SB("SBD", 1.4), //Solomon Islands
161 | SO("SOS", 0.5), //Somalia
162 | ZA("ZAR", 0.8), //South Africa
163 | SS("SSP", 0.7), //South Sudan
164 | ES("EUR", 1.3), //Spain
165 | LK("LKR", 0.4), //Sri Lanka
166 | SD("SDG", 0.5), //Sudan
167 | SR("SRD", 0.9), //Suriname
168 | SE("SEK", 1.9), //Sweden
169 | CH("CHF", 3.8), //Switzerland
170 | SY("SYP", 0.5), //Syria
171 | TW("TWD", 0.9), //Taiwan
172 | TJ("TJS", 0.3), //Tajikistan
173 | TZ("TZS", 0.7), //Tanzania
174 | TH("THB", 0.6), //Thailand
175 | TL("USD", 0.8), //Timor-Leste
176 | TG("XOF", 0.7), //Togo
177 | TO("TOP", 0.9), //Tonga
178 | TT("TTD", 1.0), //Trinidad and Tobago
179 | TN("TND", 0.5), //Tunisia
180 | TR("TRY", 0.7), //Turkey
181 | TM("TMT", 0.4), //Turkmenistan
182 | TV("AUD", 1.2), //Tuvalu
183 | UG("UGX", 0.6), //Uganda
184 | UA("UAH", 0.5), //Ukraine
185 | AE("AED", 0.8), //United Arab Emirates
186 | GB("GBP", 2.5), //United Kingdom
187 | US("USD", 2.0), //United States
188 | UY("UYU", 1.1), //Uruguay
189 | UZ("UZS", 0.5), //Uzbekistan
190 | VU("VUV", 0.9), //Vanuatu
191 | VA("EUR", 2.0), //Vatican City
192 | VE("VES", 0.5), //Venezuela
193 | VN("VND", 0.5), //Vietnam
194 | YE("YER", 0.6), //Yemen
195 | ZM("ZMW", 1.0), //Zambia
196 | ZW("ZWL", 1.2); //Zimbabwe
197 |
198 | private final String currency;
199 | private final double priceIndex;
200 |
201 |
202 | CountryCode(String currency, double priceIndex) {
203 | this.currency = currency;
204 | this.priceIndex = priceIndex;
205 | }
206 |
207 | public String getCurrency() {
208 | return currency;
209 | }
210 |
211 | public double getPriceIndex() {
212 | return priceIndex;
213 | }
214 |
215 | }
216 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/enums/DriverInfoFillingStatus.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.enums;
2 |
3 | public enum DriverInfoFillingStatus {
4 | WAITING_CAR_MODEL,
5 | WAITING_CAR_COLOR,
6 | WAITING_CAR_NUMBER,
7 | WAITING_LOCATION,
8 | INFO_IS_FILLED
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/enums/OrderStatus.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.enums;
2 |
3 | public enum OrderStatus {
4 | WAITING_PICKUP_ADDRESS,
5 | WAITING_DESTINATION_ADDRESS,
6 | WAITING_IF_NOTES_NEEDED,
7 | WAITING_NOTES,
8 | WAITING_PRICE,
9 | WAITING_DEPARTURE_DETAILS,
10 | PASSENGER_CONFIRMATION_WAITING,
11 | DRIVER_WAITING,
12 | WAITING_DRIVER_LOCATION,
13 | DRIVER_ACCEPTED,
14 | DRIVER_ON_PICKUP,
15 | ORDER_FINISHED,
16 | ORDER_CANCELED,
17 | POSTPONED_CONVERSATION_RESULT_WAITING
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/enums/OrderType.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.enums;
2 |
3 | public enum OrderType {
4 | IMMEDIATE,
5 | POSTPONED
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/enums/UserRole.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.enums;
2 |
3 | public enum UserRole {
4 | DRIVER,
5 | PASSENGER,
6 | SUPER_ADMIN
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/enums/UserStatus.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.enums;
2 |
3 | public enum UserStatus {
4 |
5 | WAITING_USER_LOCALIZATION,
6 | WAITING_USER_CONTACT,
7 | WAITING_ROLE,
8 | ACTIVE,
9 | IN_SETTINGS_MENU,
10 | EDIT_USER_NAME,
11 | EDIT_PHONE_NUMBER,
12 | EDIT_SHARE_PHONE_NUMBER,
13 | BANNED
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/helpers/AddressHelper.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.helpers;
2 |
3 | import org.json.JSONObject;
4 |
5 | import java.io.IOException;
6 | import java.net.URI;
7 | import java.net.URISyntaxException;
8 | import java.net.http.HttpClient;
9 | import java.net.http.HttpRequest;
10 | import java.net.http.HttpResponse;
11 |
12 | import static com.companerobot.constants.URLs.OPEN_STREET_MAP_BASE_URL;
13 |
14 | public class AddressHelper {
15 |
16 | public static JSONObject getAddressByCoordinates(double latitude, double longitude, int zoom) {
17 |
18 | HttpRequest request;
19 | String response;
20 | try {
21 | request = HttpRequest.newBuilder()
22 | .uri(new URI(OPEN_STREET_MAP_BASE_URL + "reverse?format=jsonv2&lat=" + latitude + "&lon=" + longitude + "&zoom=" + zoom))
23 | .GET()
24 | .build();
25 |
26 | response = HttpClient.newBuilder()
27 | .build()
28 | .send(request, HttpResponse.BodyHandlers.ofString()).body();
29 | } catch (URISyntaxException | IOException | InterruptedException e) {
30 | throw new RuntimeException(e);
31 | }
32 |
33 | //https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=47.56860&lon=-53.55615&zoom=18
34 |
35 | return new JSONObject(response);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/helpers/CipherHelper.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.helpers;
2 |
3 | import javax.crypto.*;
4 | import javax.crypto.spec.SecretKeySpec;
5 | import java.security.InvalidKeyException;
6 | import java.security.NoSuchAlgorithmException;
7 | import java.util.Base64;
8 |
9 | import static com.companerobot.constants.ExecutionConstants.CIPHER_ALGORITHM;
10 | import static com.companerobot.constants.ExecutionConstants.CIPHER_KEY;
11 |
12 | public class CipherHelper {
13 |
14 | public static String encrypt(String inputText) {
15 |
16 | Cipher cipher;
17 | try {
18 | cipher = Cipher.getInstance(CIPHER_ALGORITHM);
19 | } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
20 | throw new RuntimeException(e);
21 | }
22 | try {
23 | cipher.init(Cipher.ENCRYPT_MODE, convertStringToSecretKey(CIPHER_KEY));
24 | } catch (InvalidKeyException e) {
25 | throw new RuntimeException(e);
26 | }
27 | byte[] cipherText;
28 | try {
29 | cipherText = cipher.doFinal(inputText.getBytes());
30 | } catch (IllegalBlockSizeException | BadPaddingException e) {
31 | throw new RuntimeException(e);
32 | }
33 | return Base64.getEncoder().encodeToString(cipherText);
34 | }
35 |
36 | public static String decrypt(String encryptedText) {
37 |
38 | Cipher cipher;
39 | try {
40 | cipher = Cipher.getInstance(CIPHER_ALGORITHM);
41 | } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
42 | throw new RuntimeException(e);
43 | }
44 | try {
45 | cipher.init(Cipher.DECRYPT_MODE, convertStringToSecretKey(CIPHER_KEY));
46 | } catch (InvalidKeyException e) {
47 | throw new RuntimeException(e);
48 | }
49 | byte[] plainText;
50 | try {
51 | plainText = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
52 | } catch (IllegalBlockSizeException | BadPaddingException e) {
53 | throw new RuntimeException(e);
54 | }
55 | return new String(plainText);
56 | }
57 |
58 | public static SecretKey convertStringToSecretKey(String stringKey) {
59 | byte[] decodedKey = Base64.getDecoder().decode(stringKey);
60 | return new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
61 | }
62 |
63 | // public static SecretKey generateKey(int size) {
64 | // KeyGenerator keyGenerator;
65 | // try {
66 | // keyGenerator = KeyGenerator.getInstance("AES");
67 | // } catch (NoSuchAlgorithmException e) {
68 | // throw new RuntimeException(e);
69 | // }
70 | // keyGenerator.init(size); //256
71 | // return keyGenerator.generateKey();
72 | // }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/helpers/CyrillicStringHelper.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.helpers;
2 |
3 | import java.io.UnsupportedEncodingException;
4 | import java.nio.charset.StandardCharsets;
5 | import java.util.Locale;
6 |
7 | public class CyrillicStringHelper {
8 |
9 | public static String getCyrillicString(String text) {
10 | if (System.getProperty("os.name").toLowerCase().contains("windows") && Locale.getDefault().toString().contains("EN")) {
11 | try {
12 | return new String(text.getBytes("windows-1251"), StandardCharsets.UTF_8);
13 | } catch (UnsupportedEncodingException e) {
14 | throw new RuntimeException(e);
15 | }
16 | } else {
17 | return text;
18 | }
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/helpers/LocalizationHelper.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.helpers;
2 |
3 | import com.companerobot.constants.Locales;
4 | import com.companerobot.enums.CountryCode;
5 |
6 | import java.util.ResourceBundle;
7 |
8 | import static com.companerobot.enums.CountryCode.*;
9 |
10 | public class LocalizationHelper {
11 |
12 | private static final ResourceBundle EN_BUNDLE = ResourceBundle.getBundle("localization", Locales.US);
13 | private static final ResourceBundle UA_BUNDLE = ResourceBundle.getBundle("localization", Locales.UA);
14 | private static final ResourceBundle ES_BUNDLE = ResourceBundle.getBundle("localization", Locales.ES);
15 | private static final ResourceBundle PT_BUNDLE = ResourceBundle.getBundle("localization", Locales.PT);
16 | private static final ResourceBundle DE_BUNDLE = ResourceBundle.getBundle("localization", Locales.DE);
17 | private static final ResourceBundle FR_BUNDLE = ResourceBundle.getBundle("localization", Locales.FR);
18 |
19 |
20 | public static String getValueByCode(String localizationCode, CountryCode locale) {
21 | return getLocalizationFile(locale).getString(localizationCode);
22 | }
23 |
24 | private static ResourceBundle getLocalizationFile(CountryCode locale) {
25 |
26 | if (locale == UA) {
27 | return UA_BUNDLE;
28 |
29 | } else if (locale == ES) {
30 | return ES_BUNDLE;
31 |
32 | } else if (locale == PT) {
33 | return PT_BUNDLE;
34 |
35 | } else if (locale == DE) {
36 | return DE_BUNDLE;
37 |
38 | } else if (locale == FR) {
39 | return FR_BUNDLE;
40 |
41 | } else {
42 | return EN_BUNDLE;
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/helpers/MessageExecutionHelper.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.helpers;
2 |
3 | import com.companerobot.enums.CountryCode;
4 | import com.companerobot.enums.OrderType;
5 | import com.companerobot.keyboards.InlineKeyboardHelper;
6 | import com.companerobot.misc.DriverCollection;
7 | import com.companerobot.misc.UserCollection;
8 | import com.mongodb.client.model.geojson.Point;
9 | import com.mongodb.client.model.geojson.Position;
10 | import org.bson.Document;
11 | import org.telegram.telegrambots.client.okhttp.OkHttpTelegramClient;
12 | import org.telegram.telegrambots.meta.api.methods.send.SendLocation;
13 | import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
14 | import org.telegram.telegrambots.meta.api.methods.updatingmessages.EditMessageText;
15 | import org.telegram.telegrambots.meta.api.objects.message.MaybeInaccessibleMessage;
16 | import org.telegram.telegrambots.meta.api.objects.message.Message;
17 | import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
18 | import org.telegram.telegrambots.meta.generics.TelegramClient;
19 |
20 | import java.util.ArrayList;
21 |
22 | import static com.companerobot.constants.ExecutionConstants.BOT_TOKEN;
23 | import static com.companerobot.constants.TextMessages.*;
24 | import static com.companerobot.constants.TextValues.NOW_VALUE;
25 | import static com.companerobot.enums.OrderType.IMMEDIATE;
26 | import static java.lang.Math.toIntExact;
27 |
28 | public class MessageExecutionHelper {
29 |
30 | private static final TelegramClient telegramClient = new OkHttpTelegramClient(BOT_TOKEN);
31 |
32 | public static void sendMessageToUser(Long userId, String message) {
33 | SendMessage sendMessage = SendMessage.builder()
34 | .chatId(userId.toString())
35 | .parseMode("html")
36 | .text(message).build();
37 |
38 | sendMessageExecutor(sendMessage);
39 | }
40 |
41 | public static void sendLocationToUser(Long userId, String coordinates) {
42 | String[] parts = coordinates.split(",");
43 | double longitude = Double.parseDouble(parts[0]);
44 | double latitude = Double.parseDouble(parts[1]);
45 |
46 | SendLocation sendLocation = SendLocation.builder().chatId(userId)
47 | .latitude(latitude)
48 | .longitude(longitude)
49 | .build();
50 |
51 | try {
52 | telegramClient.executeAsync(sendLocation);
53 | } catch (TelegramApiException e) {
54 | throw new RuntimeException(e);
55 | }
56 | }
57 |
58 | public static void sendOrderToDrivers(Document order) {
59 | String orderId = order.get("orderId").toString();
60 | String pickUpAddress = CipherHelper.decrypt(order.get("pickUpAddress").toString());
61 | double pickUpAddressLatitude = Double.parseDouble(CipherHelper.decrypt(order.get("pickUpAddressLatitude").toString()));
62 | double pickUpPointLongitude = Double.parseDouble(CipherHelper.decrypt(order.get("pickUpAddressLongitude").toString()));
63 | String approximateDestinationAddress = CipherHelper.decrypt(order.get("approximateDestinationAddress").toString());
64 | String tripLength = order.get("tripLengthInKilometers").toString();
65 | String notes = CipherHelper.decrypt(order.get("notes").toString());
66 | OrderType orderType = OrderType.valueOf(order.get("orderType").toString());
67 | double price = Double.parseDouble(order.get("price").toString());
68 | String currency = order.get("currency").toString();
69 |
70 | double radiusInKms;
71 | if (orderType == IMMEDIATE) {
72 | radiusInKms = 25;
73 | } else {
74 | radiusInKms = 125;
75 | }
76 |
77 | Point pickUpPoint = new Point(new Position(pickUpPointLongitude, pickUpAddressLatitude));
78 | ArrayList driverUserIds = DriverCollection.getNearByDriversIdOnDutyList(pickUpPoint, radiusInKms);
79 | for (Long driverId : driverUserIds) {
80 | CountryCode driverLocale = UserCollection.getUserLocale(driverId);
81 |
82 | StringBuilder newOrderMessage = new StringBuilder(LocalizationHelper.getValueByCode(NEW_ORDER_BASE_MESSAGE, driverLocale)
83 | .formatted(orderId, pickUpAddress, approximateDestinationAddress, tripLength, notes));
84 |
85 | if (orderType == IMMEDIATE) {
86 | newOrderMessage.append(LocalizationHelper.getValueByCode(DEPARTURE_TIME_ORDER_MESSAGE, driverLocale)
87 | .formatted(LocalizationHelper.getValueByCode(NOW_VALUE, driverLocale)));
88 | } else {
89 | newOrderMessage.append(LocalizationHelper.getValueByCode(DEPARTURE_TIME_ORDER_MESSAGE, driverLocale)
90 | .formatted(order.get("postponedDepartureTime").toString()));
91 | }
92 |
93 | if (price == 0.00) {
94 | newOrderMessage.append(LocalizationHelper.getValueByCode(ORDER_FREE_RIDE_MESSAGE, driverLocale));
95 | } else {
96 | newOrderMessage.append(LocalizationHelper.getValueByCode(ORDER_PRICE_MESSAGE, driverLocale).formatted(price, currency));
97 | }
98 |
99 |
100 | SendMessage sendMessage = SendMessage.builder()
101 | .chatId(driverId.toString())
102 | .replyMarkup(InlineKeyboardHelper.acceptOrderMarkupKeyboard(driverId, pickUpAddressLatitude, pickUpPointLongitude))
103 | .parseMode("html")
104 | .text(newOrderMessage.toString())
105 | .build();
106 | sendMessageExecutor(sendMessage);
107 | }
108 | }
109 |
110 |
111 | //TODO: ADD BROADCAST MESSAGING FOR SUPER_ADMIN ROLE
112 |
113 |
114 | public static void sendMessageExecutor(SendMessage sendMessage) {
115 | try {
116 | telegramClient.executeAsync(sendMessage);
117 | } catch (TelegramApiException e) {
118 | throw new RuntimeException(e);
119 | }
120 | }
121 |
122 | public static void editMessage(MaybeInaccessibleMessage message, String text) {
123 | long messageId = message.getMessageId();
124 | long chatId = message.getChatId();
125 |
126 | EditMessageText updatedMessage = EditMessageText.builder()
127 | .chatId(chatId)
128 | .messageId(toIntExact(messageId))
129 | .text(text)
130 | .build();
131 |
132 | try {
133 | telegramClient.executeAsync(updatedMessage);
134 | } catch (TelegramApiException e) {
135 | throw new RuntimeException(e);
136 | }
137 | }
138 |
139 | }
140 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/helpers/PriceCalculatingHelper.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.helpers;
2 |
3 | import org.json.JSONObject;
4 |
5 | import java.io.IOException;
6 | import java.net.URI;
7 | import java.net.URISyntaxException;
8 | import java.net.http.HttpClient;
9 | import java.net.http.HttpRequest;
10 | import java.net.http.HttpResponse;
11 |
12 | import static com.companerobot.constants.URLs.REVOLUT_CURRENCY_CONVERTER_URL;
13 |
14 | public class PriceCalculatingHelper {
15 |
16 | private static final double PRICE_PER_KILOMETER = 0.5;
17 | private static final double BASE_FARE = 2;
18 | private static final String DEFAULT_CURRENCY = "EUR";
19 | private static final double DEFAULT_EXCHANGE_RATE = 1.00;
20 |
21 | public static double getFarePrice(double tripLength, double countryPriceIndex) {
22 | if (tripLength < 2.00) {
23 | return BASE_FARE * countryPriceIndex;
24 | } else {
25 | double extraLength = tripLength - 2;
26 | return (BASE_FARE + (extraLength * PRICE_PER_KILOMETER)) * countryPriceIndex;
27 | }
28 | }
29 |
30 | public static JSONObject getExchangeRateByCurrency(String currency) {
31 | HttpRequest request;
32 | String response;
33 | try {
34 | request = HttpRequest.newBuilder()
35 | .uri(new URI(REVOLUT_CURRENCY_CONVERTER_URL + currency))
36 | .GET()
37 | .build();
38 |
39 | response = HttpClient.newBuilder()
40 | .build()
41 | .send(request, HttpResponse.BodyHandlers.ofString()).body();
42 | } catch (URISyntaxException | IOException | InterruptedException e) {
43 | throw new RuntimeException(e);
44 | }
45 |
46 | return new JSONObject(response);
47 | }
48 |
49 | public static double convertPriceToLocalCurrency(double indexedPrice, String countryCurrency) {
50 | double exchangeRate = determineExchangeRate(countryCurrency);
51 | return indexedPrice * exchangeRate;
52 | }
53 |
54 | private static double determineExchangeRate(String countryCurrency) {
55 | if (countryCurrency.equals(DEFAULT_CURRENCY)) {
56 | return DEFAULT_EXCHANGE_RATE;
57 | }
58 |
59 | JSONObject currencyResponse = PriceCalculatingHelper.getExchangeRateByCurrency(countryCurrency);
60 |
61 | if (currencyResponse.has("rate")) {
62 | return currencyResponse.getDouble("rate");
63 | } else {
64 | return DEFAULT_EXCHANGE_RATE;
65 | }
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/helpers/PriceHelper.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.helpers;
2 |
3 | public class PriceHelper {
4 |
5 | public static double convertStringToDouble(String string) {
6 | string = string.replaceAll(",", ".").trim();
7 | string = string.replaceAll(" ", "");
8 | return Double.parseDouble(string);
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/helpers/RestrictionHelper.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.helpers;
2 |
3 | import com.companerobot.misc.RestrictedAreasCollection;
4 |
5 | import java.util.ArrayList;
6 |
7 | public class RestrictionHelper {
8 |
9 | private static final ArrayList restrictedCountries = RestrictedAreasCollection.getRestrictedCountriesList();
10 | private static final ArrayList restrictedPhoneNumbersList = RestrictedAreasCollection.getRestrictedPhoneNumbersList();
11 |
12 |
13 | public static boolean isRestrictedLocation(double latitude, double longitude) {
14 | return restrictedCountries.contains(AddressHelper.getAddressByCoordinates(latitude, longitude, 1)
15 | .getJSONObject("address").getString("country_code").toUpperCase());
16 | }
17 |
18 | public static boolean isRestrictedPhoneNumber(String phoneNumber) {
19 | return restrictedPhoneNumbersList.stream()
20 | .anyMatch(phoneNumber::startsWith);
21 | }
22 |
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/helpers/RoutingHelper.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.helpers;
2 |
3 | import org.json.JSONObject;
4 |
5 | import java.io.IOException;
6 | import java.net.URI;
7 | import java.net.URISyntaxException;
8 | import java.net.http.HttpClient;
9 | import java.net.http.HttpRequest;
10 | import java.net.http.HttpResponse;
11 | import java.text.DecimalFormat;
12 | import java.text.DecimalFormatSymbols;
13 |
14 | import static com.companerobot.constants.URLs.OSRM_BASE_URL;
15 |
16 | public class RoutingHelper {
17 |
18 | public static JSONObject getTripData(String startPoint, String finishPoint) {
19 | HttpRequest request;
20 | String response;
21 | try {
22 | request = HttpRequest.newBuilder()
23 | .uri(new URI(OSRM_BASE_URL + "/v1/driving/" + startPoint + ";" + finishPoint))
24 | .GET()
25 | .build();
26 |
27 | response = HttpClient.newBuilder()
28 | .build()
29 | .send(request, HttpResponse.BodyHandlers.ofString()).body();
30 | } catch (URISyntaxException | IOException | InterruptedException e) {
31 | throw new RuntimeException(e);
32 | }
33 |
34 | return new JSONObject(response).getJSONArray("routes").getJSONObject(0);
35 | }
36 |
37 | public static int getTripDurationInMinutes(double tripDurationInSec) {
38 | return (int) Math.ceil(tripDurationInSec / 60);
39 | }
40 |
41 | public static double getTripLengthInKilometers(double tripLength) {
42 | DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
43 | symbols.setDecimalSeparator('.');
44 | DecimalFormat decimalFormat = new DecimalFormat("#.##", symbols);
45 | return Double.parseDouble(decimalFormat.format(tripLength * 0.001));
46 | }
47 | }
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/keyboards/InlineKeyboardHelper.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.keyboards;
2 |
3 | import com.companerobot.enums.CountryCode;
4 | import com.companerobot.helpers.LocalizationHelper;
5 | import com.companerobot.misc.UserCollection;
6 | import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
7 | import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
8 | import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;
9 | import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardRow;
10 |
11 | import static com.companerobot.constants.Callbacks.*;
12 | import static com.companerobot.constants.InlineButtonNames.*;
13 | import static com.companerobot.constants.URLs.GOOGLE_MAPS_BASE_URL;
14 |
15 | public class InlineKeyboardHelper {
16 |
17 | public static InlineKeyboardMarkup acceptOrderMarkupKeyboard(Long driverId, double pickUpAddressLatitude, double pickUpPointLongitude) {
18 | CountryCode driverLocale = UserCollection.getUserLocale(driverId);
19 | String googleMapURL = String.format("%s%s,%s", GOOGLE_MAPS_BASE_URL, pickUpAddressLatitude, pickUpPointLongitude);
20 |
21 | InlineKeyboardButton acceptButton = InlineKeyboardButton.builder()
22 | .text(LocalizationHelper.getValueByCode(ACCEPT_INLINE_TEXT, driverLocale))
23 | .callbackData(ACCEPT_ORDER_CALLBACK)
24 | .build();
25 |
26 | InlineKeyboardButton openPickupPoint = InlineKeyboardButton.builder()
27 | .text(LocalizationHelper.getValueByCode(OPEN_PICKUP_POINT_INLINE_TEXT, driverLocale))
28 | .url(googleMapURL)
29 | .build();
30 |
31 | return InlineKeyboardMarkup.builder()
32 | .keyboardRow(new InlineKeyboardRow(acceptButton))
33 | .keyboardRow(new InlineKeyboardRow(openPickupPoint)).build();
34 | }
35 |
36 |
37 | public static InlineKeyboardMarkup destinationPointMarkupKeyboard(Long driverId, String destinationAddressLatitude, String destinationAddressLongitude) {
38 | CountryCode driverLocale = UserCollection.getUserLocale(driverId);
39 | String googleMapURL = String.format("%s%s,%s", GOOGLE_MAPS_BASE_URL, destinationAddressLatitude, destinationAddressLongitude);
40 |
41 | InlineKeyboardButton openDestinationPoint = InlineKeyboardButton.builder()
42 | .text(LocalizationHelper.getValueByCode(OPEN_DESTINATION_POINT_INLINE_TEXT, driverLocale))
43 | .url(googleMapURL)
44 | .build();
45 |
46 | return InlineKeyboardMarkup.builder()
47 | .keyboardRow(new InlineKeyboardRow(openDestinationPoint)).build();
48 | }
49 |
50 | public static InlineKeyboardMarkup openWallet(Long passengerId) {
51 | CountryCode passengerLocale = UserCollection.getUserLocale(passengerId);
52 |
53 | InlineKeyboardButton openWalletButton = InlineKeyboardButton.builder()
54 | .text(LocalizationHelper.getValueByCode(WALLET_INLINE_TEXT, passengerLocale))
55 | .url("https://t.me/wallet/start")
56 | .build();
57 |
58 | return InlineKeyboardMarkup.builder()
59 | .keyboardRow(new InlineKeyboardRow(openWalletButton)).build();
60 | }
61 |
62 |
63 | public static SendMessage passengerContactsMarkupKeyboard(Long driverId, Long passengerId, String message) {
64 | CountryCode driverLocale = UserCollection.getUserLocale(driverId);
65 |
66 | InlineKeyboardButton writeToUserButton = InlineKeyboardButton.builder()
67 | .text(LocalizationHelper.getValueByCode(WRITE_TO_PASSENGER_INLINE_TEXT, driverLocale))
68 | .url("https://t.me/" + UserCollection.getUserTag(passengerId))
69 | .build();
70 |
71 | InlineKeyboardMarkup inlineKeyboardMarkup = InlineKeyboardMarkup.builder()
72 | .keyboardRow(new InlineKeyboardRow(writeToUserButton))
73 | .build();
74 |
75 | return SendMessage.builder()
76 | .parseMode("html")
77 | .chatId(driverId.toString())
78 | .replyMarkup(inlineKeyboardMarkup)
79 | .text(message)
80 | .build();
81 | }
82 |
83 |
84 | public static SendMessage changeDepartureTimeKeyboard(Long passengerId, String message) {
85 | CountryCode passengerLocale = UserCollection.getUserLocale(passengerId);
86 |
87 | InlineKeyboardButton addDepartureDateDetailsButton = InlineKeyboardButton.builder()
88 | .text(LocalizationHelper.getValueByCode(ADD_POSTPONED_DEPARTURE_DETAILS_INLINE_TEXT, passengerLocale))
89 | .callbackData(ADD_POSTPONED_DEPARTURE_DETAILS_CALLBACK)
90 | .build();
91 |
92 | InlineKeyboardMarkup inlineKeyboardMarkup = InlineKeyboardMarkup.builder()
93 | .keyboardRow(new InlineKeyboardRow(addDepartureDateDetailsButton))
94 | .build();
95 |
96 | return SendMessage.builder()
97 | .parseMode("html")
98 | .chatId(passengerId.toString())
99 | .replyMarkup(inlineKeyboardMarkup)
100 | .text(message)
101 | .build();
102 | }
103 |
104 |
105 | public static SendMessage driverContactsMarkupKeyboard(Long driverId, Long passengerId, String message) {
106 | CountryCode passengerLocale = UserCollection.getUserLocale(passengerId);
107 |
108 | InlineKeyboardButton writeToUserButton = InlineKeyboardButton.builder()
109 | .text(LocalizationHelper.getValueByCode(WRITE_TO_DRIVER_INLINE_TEXT, passengerLocale))
110 | .url("https://t.me/" + UserCollection.getUserTag(driverId))
111 | .build();
112 |
113 | InlineKeyboardMarkup inlineKeyboardMarkup = InlineKeyboardMarkup.builder()
114 | .keyboardRow(new InlineKeyboardRow(writeToUserButton))
115 | .build();
116 |
117 | return SendMessage.builder()
118 | .parseMode("html")
119 | .chatId(passengerId.toString())
120 | .replyMarkup(inlineKeyboardMarkup)
121 | .text(message)
122 | .build();
123 | }
124 |
125 |
126 | public static SendMessage requestRideReviewMarkupKeyboard(Long userId, String message) {
127 | InlineKeyboardButton likeButton = InlineKeyboardButton.builder()
128 | .text(LIKE_RIDE_INLINE_TEXT)
129 | .callbackData(LIKE_RIDE_CALLBACK)
130 | .build();
131 |
132 | InlineKeyboardButton dislikeButton = InlineKeyboardButton.builder()
133 | .text(DISLIKE_RIDE_INLINE_TEXT)
134 | .callbackData(DISLIKE_RIDE_CALLBACK)
135 | .build();
136 |
137 | InlineKeyboardMarkup inlineKeyboardMarkup = InlineKeyboardMarkup.builder()
138 | .keyboardRow(new InlineKeyboardRow(likeButton, dislikeButton))
139 | .build();
140 |
141 | return SendMessage.builder()
142 | .parseMode("html")
143 | .chatId(userId)
144 | .replyMarkup(inlineKeyboardMarkup)
145 | .text(message)
146 | .build();
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/keyboards/UserManagementReplyKeyboards.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.keyboards;
2 |
3 | import com.companerobot.enums.CountryCode;
4 | import com.companerobot.helpers.LocalizationHelper;
5 | import com.companerobot.misc.UserCollection;
6 | import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
7 | import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboardMarkup;
8 | import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardButton;
9 | import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardRow;
10 |
11 | import static com.companerobot.constants.HookMessages.*;
12 |
13 | public class UserManagementReplyKeyboards {
14 |
15 | public static SendMessage openedSettingsKeyboard(Long userId, String message) {
16 | CountryCode userLocale = UserCollection.getUserLocale(userId);
17 |
18 | KeyboardButton editNameButton = KeyboardButton.builder()
19 | .text(LocalizationHelper.getValueByCode(EDIT_USER_NAME_HOOK_MESSAGE, userLocale))
20 | .build();
21 |
22 | KeyboardButton editPhoneNumberButton = KeyboardButton.builder()
23 | .text(LocalizationHelper.getValueByCode(EDIT_PHONE_NUMBER_HOOK_MESSAGE, userLocale))
24 | .build();
25 |
26 | KeyboardButton editSharePhoneNumberButton = KeyboardButton.builder()
27 | .text(LocalizationHelper.getValueByCode(EDIT_SHARE_PHONE_NUMBER_HOOK_MESSAGE, userLocale))
28 | .build();
29 |
30 | KeyboardButton exitSettingsButton = KeyboardButton.builder()
31 | .text(LocalizationHelper.getValueByCode(EXIT_SETTINGS_HOOK_MESSAGE, userLocale))
32 | .build();
33 |
34 |
35 | KeyboardRow keyboardRow1 = new KeyboardRow();
36 | keyboardRow1.add(editNameButton);
37 |
38 | KeyboardRow keyboardRow2 = new KeyboardRow();
39 | keyboardRow2.add(editPhoneNumberButton);
40 |
41 | KeyboardRow keyboardRow3 = new KeyboardRow();
42 | keyboardRow3.add(editSharePhoneNumberButton);
43 |
44 | KeyboardRow keyboardRow4 = new KeyboardRow();
45 | keyboardRow4.add(exitSettingsButton);
46 |
47 | ReplyKeyboardMarkup replyKeyboardMarkup = ReplyKeyboardMarkup.builder()
48 | .keyboardRow(keyboardRow1)
49 | .keyboardRow(keyboardRow2)
50 | .keyboardRow(keyboardRow3)
51 | .keyboardRow(keyboardRow4)
52 | .resizeKeyboard(true)
53 | .build();
54 |
55 | return SendMessage.builder()
56 | .chatId(userId.toString())
57 | .replyMarkup(replyKeyboardMarkup)
58 | .parseMode("html")
59 | .text(message)
60 | .build();
61 | }
62 |
63 | public static SendMessage changeUsernameKeyboard(Long userId, String message) {
64 | CountryCode userLocale = UserCollection.getUserLocale(userId);
65 |
66 | KeyboardButton backToSettingsMenuButton = KeyboardButton.builder()
67 | .text(LocalizationHelper.getValueByCode(BACK_TO_PREVIOUS_PAGE_HOOK_MESSAGE, userLocale))
68 | .build();
69 |
70 | KeyboardRow keyboardRow1 = new KeyboardRow();
71 | keyboardRow1.add(backToSettingsMenuButton);
72 |
73 | ReplyKeyboardMarkup replyKeyboardMarkup = ReplyKeyboardMarkup.builder()
74 | .keyboardRow(keyboardRow1)
75 | .resizeKeyboard(true)
76 | .build();
77 |
78 | return SendMessage.builder()
79 | .chatId(userId.toString())
80 | .replyMarkup(replyKeyboardMarkup)
81 | .parseMode("html")
82 | .text(message)
83 | .build();
84 | }
85 |
86 | public static SendMessage changePhoneNumberKeyboard(Long userId, String message) {
87 | CountryCode userLocale = UserCollection.getUserLocale(userId);
88 |
89 | KeyboardButton sendContactButton = KeyboardButton.builder()
90 | .text(LocalizationHelper.getValueByCode(SHARE_MY_CONTACT_HOOK_MESSAGE, userLocale))
91 | .requestContact(true)
92 | .build();
93 |
94 | KeyboardButton backToSettingsMenuButton = KeyboardButton.builder()
95 | .text(LocalizationHelper.getValueByCode(BACK_TO_PREVIOUS_PAGE_HOOK_MESSAGE, userLocale))
96 | .build();
97 |
98 | KeyboardRow keyboardRow1 = new KeyboardRow();
99 | keyboardRow1.add(sendContactButton);
100 |
101 | KeyboardRow keyboardRow2 = new KeyboardRow();
102 | keyboardRow2.add(backToSettingsMenuButton);
103 |
104 | ReplyKeyboardMarkup replyKeyboardMarkup = ReplyKeyboardMarkup.builder()
105 | .keyboardRow(keyboardRow1)
106 | .keyboardRow(keyboardRow2)
107 | .resizeKeyboard(true)
108 | .build();
109 |
110 | return SendMessage.builder()
111 | .chatId(userId.toString())
112 | .replyMarkup(replyKeyboardMarkup)
113 | .parseMode("html")
114 | .text(message)
115 | .build();
116 | }
117 |
118 | public static SendMessage updateOrRemovePhoneNumberKeyboard(Long userId, String message) {
119 | CountryCode userLocale = UserCollection.getUserLocale(userId);
120 |
121 | KeyboardButton sendContactButton = KeyboardButton.builder()
122 | .text(LocalizationHelper.getValueByCode(SHARE_MY_CONTACT_HOOK_MESSAGE, userLocale))
123 | .requestContact(true)
124 | .build();
125 |
126 | KeyboardButton removeContactButton = KeyboardButton.builder()
127 | .text(LocalizationHelper.getValueByCode(REMOVE_PHONE_NUMBER_HOOK_MESSAGE, userLocale))
128 | .build();
129 |
130 | KeyboardButton backToSettingsMenuButton = KeyboardButton.builder()
131 | .text(LocalizationHelper.getValueByCode(BACK_TO_PREVIOUS_PAGE_HOOK_MESSAGE, userLocale))
132 | .build();
133 |
134 | KeyboardRow keyboardRow1 = new KeyboardRow();
135 | keyboardRow1.add(sendContactButton);
136 |
137 | KeyboardRow keyboardRow2 = new KeyboardRow();
138 | keyboardRow2.add(removeContactButton);
139 |
140 | KeyboardRow keyboardRow3 = new KeyboardRow();
141 | keyboardRow3.add(backToSettingsMenuButton);
142 |
143 | ReplyKeyboardMarkup replyKeyboardMarkup = ReplyKeyboardMarkup.builder()
144 | .keyboardRow(keyboardRow1)
145 | .keyboardRow(keyboardRow2)
146 | .keyboardRow(keyboardRow3)
147 | .resizeKeyboard(true)
148 | .build();
149 |
150 | return SendMessage.builder()
151 | .chatId(userId.toString())
152 | .replyMarkup(replyKeyboardMarkup)
153 | .parseMode("html")
154 | .text(message)
155 | .build();
156 | }
157 |
158 | public static SendMessage hiddenNumberKeyboard(Long userId, String message) {
159 | CountryCode userLocale = UserCollection.getUserLocale(userId);
160 |
161 | KeyboardButton revealPhoneNumberButton = KeyboardButton.builder()
162 | .text(LocalizationHelper.getValueByCode(REVEAL_PHONE_NUMBER_HOOK_MESSAGE, userLocale))
163 | .build();
164 |
165 | KeyboardButton backToSettingsMenuButton = KeyboardButton.builder()
166 | .text(LocalizationHelper.getValueByCode(BACK_TO_PREVIOUS_PAGE_HOOK_MESSAGE, userLocale))
167 | .build();
168 |
169 | KeyboardRow keyboardRow1 = new KeyboardRow();
170 | keyboardRow1.add(revealPhoneNumberButton);
171 |
172 | KeyboardRow keyboardRow2 = new KeyboardRow();
173 | keyboardRow2.add(backToSettingsMenuButton);
174 |
175 | ReplyKeyboardMarkup replyKeyboardMarkup = ReplyKeyboardMarkup.builder()
176 | .keyboardRow(keyboardRow1)
177 | .keyboardRow(keyboardRow2)
178 | .resizeKeyboard(true)
179 | .build();
180 |
181 | return SendMessage.builder()
182 | .chatId(userId.toString())
183 | .replyMarkup(replyKeyboardMarkup)
184 | .parseMode("html")
185 | .text(message)
186 | .build();
187 | }
188 |
189 | public static SendMessage notHiddenNumberKeyboard(Long userId, String message) {
190 | CountryCode userLocale = UserCollection.getUserLocale(userId);
191 |
192 | KeyboardButton hidePhoneNumberButton = KeyboardButton.builder()
193 | .text(LocalizationHelper.getValueByCode(HIDE_PHONE_NUMBER_HOOK_MESSAGE, userLocale))
194 | .build();
195 |
196 | KeyboardButton backToSettingsMenuButton = KeyboardButton.builder()
197 | .text(LocalizationHelper.getValueByCode(BACK_TO_PREVIOUS_PAGE_HOOK_MESSAGE, userLocale))
198 | .build();
199 |
200 | KeyboardRow keyboardRow1 = new KeyboardRow();
201 | keyboardRow1.add(hidePhoneNumberButton);
202 |
203 | KeyboardRow keyboardRow2 = new KeyboardRow();
204 | keyboardRow2.add(backToSettingsMenuButton);
205 |
206 | ReplyKeyboardMarkup replyKeyboardMarkup = ReplyKeyboardMarkup.builder()
207 | .keyboardRow(keyboardRow1)
208 | .keyboardRow(keyboardRow2)
209 | .resizeKeyboard(true)
210 | .build();
211 |
212 | return SendMessage.builder()
213 | .chatId(userId.toString())
214 | .replyMarkup(replyKeyboardMarkup)
215 | .parseMode("html")
216 | .text(message)
217 | .build();
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/misc/DriverCollection.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.misc;
2 |
3 | import com.companerobot.enums.DriverInfoFillingStatus;
4 | import com.companerobot.helpers.CipherHelper;
5 | import com.mongodb.client.FindIterable;
6 | import com.mongodb.client.MongoCollection;
7 | import com.mongodb.client.model.Filters;
8 | import com.mongodb.client.model.Updates;
9 | import com.mongodb.client.model.geojson.Point;
10 | import org.bson.Document;
11 |
12 | import java.util.ArrayList;
13 |
14 | import static com.companerobot.enums.DriverInfoFillingStatus.WAITING_CAR_MODEL;
15 | import static com.companerobot.misc.MongoBaseClass.database;
16 |
17 | public class DriverCollection {
18 |
19 | protected static final MongoCollection driverCollection = database.getCollection("driversInfo");
20 |
21 | public static void addDriverToDB(Long userId) {
22 | Document document = new Document();
23 | document.put("userId", userId);
24 | document.put("carModel", null);
25 | document.put("carColor", null);
26 | document.put("carNumber", null);
27 | document.put("location", null);
28 | document.put("isWaitingForNewTrip", false);
29 | document.put("driverInfoFillingStatus", WAITING_CAR_MODEL);
30 | driverCollection.insertOne(document);
31 | // driverCollection.createIndex(Indexes.geo2dsphere("location")); //TODO: Create index only once
32 | }
33 |
34 | public static Document getDriverInfoByDriverId(Long userId) {
35 | return driverCollection.find(Filters.eq("userId", userId)).first();
36 | }
37 |
38 | public static ArrayList getNearByDriversIdOnDutyList(Point point, double radiusInKms) {
39 | ArrayList driverUserIds = new ArrayList<>();
40 | double minDistance = 0;
41 | double maxDistance = radiusInKms * 1000;
42 |
43 | FindIterable nearbyDrivers = driverCollection.find(
44 | Filters.and(
45 | Filters.nearSphere("location", point, maxDistance, minDistance),
46 | Filters.eq("isWaitingForNewTrip", true)
47 | )
48 | );
49 |
50 | for (Document document : nearbyDrivers) {
51 | driverUserIds.add(Long.valueOf(document.get("userId").toString()));
52 | }
53 |
54 | return driverUserIds;
55 | }
56 |
57 | public static void setCarModel(Long userId, String carModel) {
58 | driverCollection.updateOne(Filters.eq("userId", userId),
59 | Updates.set("carModel", carModel));
60 | }
61 |
62 | public static void setCarColor(Long userId, String carColor) {
63 | driverCollection.updateOne(Filters.eq("userId", userId),
64 | Updates.set("carColor", carColor));
65 | }
66 |
67 | public static void setLocation(Long userId, Point point) {
68 | driverCollection.updateOne(Filters.eq("userId", userId),
69 | Updates.set("location", point));
70 | }
71 |
72 | public static void setCarNumber(Long userId, String carNumber) {
73 | driverCollection.updateOne(Filters.eq("userId", userId),
74 | Updates.set("carNumber", CipherHelper.encrypt(carNumber)));
75 | }
76 |
77 | public static void setIsWaitingForNewTrip(Long userId, boolean isWaitingForNewTrip) {
78 | driverCollection.updateOne(Filters.eq("userId", userId),
79 | Updates.set("isWaitingForNewTrip", isWaitingForNewTrip));
80 | }
81 |
82 | public static void setDriverInfoFillingStatus(Long userId, DriverInfoFillingStatus driverInfoFillingStatus) {
83 | driverCollection.updateOne(Filters.eq("userId", userId),
84 | Updates.set("driverInfoFillingStatus", driverInfoFillingStatus));
85 | }
86 |
87 | public static boolean getIsWaitingForNewTrip(Long userId) {
88 | return Boolean.parseBoolean(driverCollection.find(
89 | Filters.eq("userId", userId))
90 | .first()
91 | .get("isWaitingForNewTrip")
92 | .toString());
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/misc/MongoBaseClass.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.misc;
2 |
3 | import com.mongodb.client.MongoClient;
4 | import com.mongodb.client.MongoClients;
5 | import com.mongodb.client.MongoDatabase;
6 |
7 | import static com.companerobot.constants.ExecutionConstants.MONGODB_CLIENT_URL;
8 |
9 | public class MongoBaseClass {
10 | protected static final MongoClient mongoClient = MongoClients.create(MONGODB_CLIENT_URL);
11 | protected static MongoDatabase database = mongoClient.getDatabase("CompaneroBotDB");
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/misc/OrderCollection.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.misc;
2 |
3 | import com.companerobot.enums.CountryCode;
4 | import com.companerobot.enums.OrderStatus;
5 | import com.companerobot.enums.OrderType;
6 | import com.companerobot.helpers.CipherHelper;
7 | import com.mongodb.client.MongoCollection;
8 | import com.mongodb.client.model.Filters;
9 | import com.mongodb.client.model.Updates;
10 | import org.bson.Document;
11 |
12 | import java.util.Date;
13 | import java.util.UUID;
14 |
15 | import static com.companerobot.enums.OrderStatus.*;
16 | import static com.companerobot.enums.OrderType.IMMEDIATE;
17 |
18 | public class OrderCollection extends MongoBaseClass {
19 |
20 | protected static final MongoCollection orderCollection = database.getCollection("orders");
21 |
22 | public static void createNewOrder(Long userId) {
23 | Document document = new Document();
24 | document.put("orderId", String.valueOf(UUID.randomUUID()));
25 | document.put("userId", userId);
26 | document.put("pickUpAddress", null);
27 | document.put("pickUpAddressLongitude", null);
28 | document.put("pickUpAddressLatitude", null);
29 | document.put("destinationAddress", null);
30 | document.put("destinationAddressLongitude", null);
31 | document.put("destinationAddressLatitude", null);
32 | document.put("approximateDestinationAddress", null);
33 | document.put("countryCode", null);
34 | document.put("tripLengthInKilometers", null);
35 | document.put("notes", null);
36 | document.put("orderType", IMMEDIATE);
37 | document.put("orderStatus", WAITING_PICKUP_ADDRESS);
38 | document.put("postponedDepartureTime", null);
39 | document.put("price", null);
40 | document.put("currency", null);
41 | document.put("driverId", null);
42 | document.put("createdAt", new Date());
43 | orderCollection.insertOne(document);
44 | }
45 |
46 | public static Document getOrderByPassengerIdAndStatus(Long userId, OrderStatus orderStatus) {
47 | return orderCollection.find(
48 | Filters.and(
49 | Filters.eq("userId", userId),
50 | Filters.eq("orderStatus", orderStatus))).first();
51 | }
52 |
53 | public static Document getUnfinishedOrderByPassengerId(Long userId) {
54 | return orderCollection.find(
55 | Filters.and(
56 | Filters.eq("userId", userId),
57 | Filters.ne("orderStatus", ORDER_FINISHED),
58 | Filters.ne("orderStatus", ORDER_CANCELED))).first();
59 | }
60 |
61 | public static boolean isPassengerHasUnfinishedTrips(Long userId) {
62 | return orderCollection.find(
63 | Filters.and(
64 | Filters.eq("userId", userId),
65 | Filters.ne("orderStatus", ORDER_FINISHED),
66 | Filters.ne("orderStatus", ORDER_CANCELED))).first() != null;
67 |
68 | }
69 |
70 | public static Document getUnfinishedOrderByDriverId(Long driverId) {
71 | return orderCollection.find(
72 | Filters.and(
73 | Filters.eq("driverId", driverId),
74 | Filters.ne("orderStatus", ORDER_FINISHED),
75 | Filters.ne("orderStatus", ORDER_CANCELED))).first();
76 | }
77 |
78 | public static boolean isDriverHasUnfinishedTrips(Long driverId) {
79 | return orderCollection.find(
80 | Filters.and(
81 | Filters.eq("driverId", driverId),
82 | Filters.ne("orderStatus", ORDER_FINISHED),
83 | Filters.ne("orderStatus", ORDER_CANCELED))).first() != null;
84 |
85 | }
86 |
87 | public static Document getOrderByDriverIdAndStatus(Long driverId, OrderStatus orderStatus) {
88 | return orderCollection.find(
89 | Filters.and(
90 | Filters.eq("driverId", driverId),
91 | Filters.eq("orderStatus", orderStatus))).first();
92 | }
93 |
94 | public static Document getOrderByOrderId(String orderId) {
95 | return orderCollection.find(Filters.eq("orderId", orderId)).first();
96 | }
97 |
98 | public static void setPickUpAddress(String orderId, String pickUpAddress) {
99 | orderCollection.updateOne(Filters.eq("orderId", orderId),
100 | Updates.set("pickUpAddress", CipherHelper.encrypt(pickUpAddress)));
101 | }
102 |
103 | public static void setCountryCode(String orderId, CountryCode countryCode) {
104 | orderCollection.updateOne(Filters.eq("orderId", orderId),
105 | Updates.set("countryCode", countryCode));
106 | }
107 |
108 | public static CountryCode getOrderCountryCode(String orderId) {
109 | return CountryCode.valueOf(orderCollection.find(Filters.eq("orderId", orderId))
110 | .first()
111 | .get("countryCode")
112 | .toString());
113 | }
114 |
115 | public static void updateOrderType(String orderId, OrderType orderType) {
116 | orderCollection.updateOne(Filters.eq("orderId", orderId),
117 | Updates.set("orderType", orderType));
118 | }
119 |
120 | public static OrderType getOrderType(String orderId) {
121 | return OrderType.valueOf(orderCollection.find(Filters.eq("orderId", orderId))
122 | .first()
123 | .get("orderType")
124 | .toString());
125 | }
126 |
127 | public static void setPostponedDepartureTime(String orderId, String postponedDepartureTime) {
128 | orderCollection.updateOne(Filters.eq("orderId", orderId),
129 | Updates.set("postponedDepartureTime", postponedDepartureTime));
130 | }
131 |
132 | public static void setPickUpAddressLongitude(String orderId, double longitude) {
133 | orderCollection.updateOne(Filters.eq("orderId", orderId),
134 | Updates.set("pickUpAddressLongitude", CipherHelper.encrypt(String.valueOf(longitude))));
135 | }
136 |
137 | public static void setPickUpAddressLatitude(String orderId, double latitude) {
138 | orderCollection.updateOne(Filters.eq("orderId", orderId),
139 | Updates.set("pickUpAddressLatitude", CipherHelper.encrypt(String.valueOf(latitude))));
140 | }
141 |
142 |
143 | public static void setDestinationAddress(String orderId, String destinationAddress) {
144 | orderCollection.updateOne(Filters.eq("orderId", orderId),
145 | Updates.set("destinationAddress", CipherHelper.encrypt(destinationAddress)));
146 | }
147 |
148 | public static void setDestinationAddressLongitude(String orderId, double longitude) {
149 | orderCollection.updateOne(Filters.eq("orderId", orderId),
150 | Updates.set("destinationAddressLongitude", CipherHelper.encrypt(String.valueOf(longitude))));
151 | }
152 |
153 | public static void setDestinationAddressLatitude(String orderId, double latitude) {
154 | orderCollection.updateOne(Filters.eq("orderId", orderId),
155 | Updates.set("destinationAddressLatitude", CipherHelper.encrypt(String.valueOf(latitude))));
156 | }
157 |
158 | public static void setApproximateDestinationAddress(String orderId, String approximateDestinationAddress) {
159 | orderCollection.updateOne(Filters.eq("orderId", orderId),
160 | Updates.set("approximateDestinationAddress", CipherHelper.encrypt(approximateDestinationAddress)));
161 | }
162 |
163 | public static void setTripLength(String orderId, double tripLength) {
164 | orderCollection.updateOne(Filters.eq("orderId", orderId),
165 | Updates.set("tripLengthInKilometers", tripLength));
166 | }
167 |
168 | public static double getTripLength(String orderId) {
169 | return orderCollection.find(Filters.eq("orderId", orderId))
170 | .first()
171 | .getDouble("tripLengthInKilometers");
172 | }
173 |
174 | public static void setNotes(String orderId, String notes) {
175 | orderCollection.updateOne(Filters.eq("orderId", orderId),
176 | Updates.set("notes", CipherHelper.encrypt(notes)));
177 | }
178 |
179 | public static void setDriverId(String orderId, Long driverId) {
180 | orderCollection.updateOne(Filters.eq("orderId", orderId),
181 | Updates.set("driverId", driverId));
182 | }
183 |
184 | public static void updateOrderStatus(String orderId, OrderStatus orderStatus) {
185 | orderCollection.updateOne(Filters.eq("orderId", orderId),
186 | Updates.set("orderStatus", orderStatus));
187 | }
188 |
189 | public static void setPriceForOrder(String orderId, double farePrice) {
190 | orderCollection.updateOne(Filters.eq("orderId", orderId),
191 | Updates.set("price", farePrice));
192 | }
193 |
194 | public static void setCurrencyForOrder(String orderId, String currency) {
195 | orderCollection.updateOne(Filters.eq("orderId", orderId),
196 | Updates.set("currency", currency));
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/misc/RestrictedAreasCollection.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.misc;
2 |
3 | import com.mongodb.client.FindIterable;
4 | import com.mongodb.client.MongoCollection;
5 | import org.bson.Document;
6 |
7 | import java.util.ArrayList;
8 |
9 | import static com.companerobot.misc.MongoBaseClass.database;
10 |
11 | public class RestrictedAreasCollection {
12 |
13 | private static final MongoCollection restrictedAreasCollection = database.getCollection("restrictedAreas");
14 |
15 | public static ArrayList getRestrictedCountriesList() {
16 | ArrayList restrictedAreas = new ArrayList<>();
17 | FindIterable restictedAreasDocumentsCollection = restrictedAreasCollection.find();
18 |
19 | for (Document document : restictedAreasDocumentsCollection) {
20 | restrictedAreas.add(document.get("countryCode").toString());
21 | }
22 |
23 | return restrictedAreas;
24 | }
25 |
26 | public static ArrayList getRestrictedPhoneNumbersList() {
27 | ArrayList restrictedPhoneCodes = new ArrayList<>();
28 | FindIterable restictedAreasDocumentsCollection = restrictedAreasCollection.find();
29 |
30 | for (Document document : restictedAreasDocumentsCollection) {
31 | restrictedPhoneCodes.add(document.get("phoneCode").toString());
32 | }
33 |
34 | return restrictedPhoneCodes;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/misc/ReviewCollection.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.misc;
2 |
3 | import com.mongodb.client.MongoCollection;
4 | import com.mongodb.client.model.*;
5 | import org.bson.Document;
6 |
7 | import java.math.BigDecimal;
8 | import java.math.RoundingMode;
9 | import java.util.ArrayList;
10 | import java.util.Arrays;
11 | import java.util.Date;
12 |
13 | import static com.companerobot.misc.MongoBaseClass.database;
14 | import static com.mongodb.client.model.Aggregates.*;
15 |
16 |
17 | public class ReviewCollection {
18 |
19 | protected static final MongoCollection reviewCollection = database.getCollection("reviews");
20 |
21 | public static void addNewUserToReviewDB(Long userId) {
22 | Document document = new Document();
23 | document.put("userId", userId);
24 | document.put("rating", 0.0);
25 | document.put("reviews", new ArrayList<>());
26 | reviewCollection.insertOne(document);
27 | }
28 |
29 | public static void addUserReview(Long userId, Long reviewerId, boolean isLiked) {
30 |
31 | if (!isReviewerAlreadyAddedReview(userId, reviewerId)) {
32 | addNewReview(userId, reviewerId, isLiked);
33 |
34 | } else {
35 | updateOldReview(userId, reviewerId, isLiked);
36 | }
37 |
38 | updateUserRating(userId);
39 | }
40 |
41 | private static void addNewReview(Long userId, Long reviewerId, boolean isLiked) {
42 | Date currentTime = new Date();
43 |
44 | Document reviewDocument = new Document();
45 | reviewDocument.put("reviewerId", reviewerId);
46 | reviewDocument.put("isLiked", isLiked);
47 | reviewDocument.put("createdAt", currentTime);
48 | reviewDocument.put("updatedAt", currentTime);
49 |
50 | reviewCollection.updateOne(
51 | Filters.eq("userId", userId),
52 | Updates.push("reviews", reviewDocument)
53 | );
54 | }
55 |
56 | private static void updateOldReview(Long userId, Long reviewerId, boolean isLiked) {
57 | reviewCollection.updateOne(
58 | Filters.eq("userId", userId),
59 | Updates.combine(
60 | Updates.set("reviews.$[elem].isLiked", isLiked),
61 | Updates.set("reviews.$[elem].updatedAt", new Date())),
62 | new UpdateOptions()
63 | .arrayFilters(Arrays.asList(
64 | Filters.eq("elem.reviewerId", reviewerId))
65 | )
66 | );
67 | }
68 |
69 | public static boolean isUserHasReviews(Long userId) {
70 | Document user = reviewCollection.find(Filters.eq("userId", userId)).first();
71 | return user != null;
72 | }
73 |
74 | private static int getUserLikesAmount(Long userId) {
75 | Document result = reviewCollection.aggregate(Arrays.asList(
76 | match(Filters.eq("userId", userId)),
77 | unwind("$reviews"),
78 | match(Filters.eq("reviews.isLiked", true)),
79 | count())).first();
80 |
81 | if (result != null) {
82 | return result.getInteger("count");
83 | } else {
84 | return 0;
85 | }
86 | }
87 |
88 | public static int getUserReviewsAmount(Long userId) {
89 | Document result = reviewCollection.find(Filters.eq("userId", userId))
90 | .projection(Projections.computed("reviewsSize",
91 | new Document("$size", "$reviews"))).first();
92 |
93 | if (result != null) {
94 | return result.getInteger("reviewsSize");
95 | } else {
96 | return 0;
97 | }
98 | }
99 |
100 | public static void updateUserRating(Long userId) {
101 |
102 | double userReviewsAmount = getUserReviewsAmount(userId);
103 | double userLikesAmount = getUserLikesAmount(userId);
104 |
105 | double rating = new BigDecimal(userLikesAmount / userReviewsAmount * 10).
106 | setScale(2, RoundingMode.HALF_UP).doubleValue();
107 |
108 | reviewCollection.updateOne(Filters.eq("userId", userId),
109 | Updates.set("rating", rating));
110 | }
111 |
112 | public static double getUserRating(Long userId) {
113 | return reviewCollection.find(Filters.eq("userId", userId))
114 | .first()
115 | .getDouble("rating");
116 | }
117 |
118 | public static boolean isReviewerAlreadyAddedReview(Long userId, Long reviewerId) {
119 | Document isReviewerIdReviewed = reviewCollection.find(
120 | Filters.and(
121 | Filters.eq("userId", userId),
122 | Filters.eq("reviews.reviewerId", reviewerId))).first();
123 | return isReviewerIdReviewed != null;
124 | }
125 |
126 | }
127 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/misc/UserCollection.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.misc;
2 |
3 | import com.companerobot.enums.CountryCode;
4 | import com.companerobot.enums.UserRole;
5 | import com.companerobot.enums.UserStatus;
6 | import com.companerobot.helpers.CipherHelper;
7 | import com.mongodb.client.MongoCollection;
8 | import com.mongodb.client.model.Filters;
9 | import com.mongodb.client.model.Updates;
10 | import org.bson.Document;
11 |
12 | import static com.companerobot.enums.UserStatus.WAITING_USER_LOCALIZATION;
13 |
14 | public class UserCollection extends MongoBaseClass {
15 |
16 | protected static final MongoCollection customerCollection = database.getCollection("customers");
17 |
18 | public static void addUserToDB(Long userId) {
19 | Document document = new Document();
20 | document.put("userId", userId);
21 | document.put("userRole", null);
22 | document.put("userName", null);
23 | document.put("userPhoneNumber", null);
24 | document.put("isPhoneNumberHidden", true);
25 | document.put("userTag", null);
26 | document.put("userLocale", CountryCode.US);
27 | document.put("userStatus", WAITING_USER_LOCALIZATION);
28 | customerCollection.insertOne(document);
29 | }
30 |
31 | public static void updateUserRole(Long userId, UserRole userRole) {
32 | customerCollection.updateOne(Filters.eq("userId", userId),
33 | Updates.set("userRole", userRole));
34 | }
35 |
36 | public static void updateUserLocalization(Long userId, CountryCode locale) {
37 | customerCollection.updateOne(Filters.eq("userId", userId),
38 | Updates.set("userLocale", locale));
39 | }
40 |
41 | public static void updateIsUserPhoneHidden(Long userId, boolean isPhoneNumberHidden) {
42 | customerCollection.updateOne(Filters.eq("userId", userId),
43 | Updates.set("isPhoneNumberHidden", isPhoneNumberHidden));
44 | }
45 |
46 | public static void updateUserName(Long userId, String userName) {
47 | customerCollection.updateOne(Filters.eq("userId", userId),
48 | Updates.set("userName", userName));
49 | }
50 |
51 | public static void updateUserPhoneNumber(Long userId, String userPhoneNumber) {
52 | customerCollection.updateOne(Filters.eq("userId", userId),
53 | Updates.set("userPhoneNumber", CipherHelper.encrypt(userPhoneNumber)));
54 |
55 | }
56 |
57 | public static void removeUserPhoneNumber(Long userId) {
58 | customerCollection.updateOne(Filters.eq("userId", userId),
59 | Updates.set("userPhoneNumber", null));
60 |
61 | }
62 |
63 | public static void updateUserTag(Long userId, String userTag) {
64 | if (userTag == null) {
65 | customerCollection.updateOne(Filters.eq("userId", userId),
66 | Updates.set("userTag", null));
67 | } else {
68 | customerCollection.updateOne(Filters.eq("userId", userId),
69 | Updates.set("userTag", CipherHelper.encrypt(userTag)));
70 | }
71 | }
72 |
73 | public static void updateUserStatus(Long userId, UserStatus userStatus) {
74 | customerCollection.updateOne(Filters.eq("userId", userId),
75 | Updates.set("userStatus", userStatus));
76 | }
77 |
78 | public static boolean isUserExist(Long userId) {
79 | Document user = customerCollection.find(Filters.eq("userId", userId)).first();
80 | return user != null;
81 | }
82 |
83 | public static UserRole getUserRole(Long userId) {
84 | Object userRole = customerCollection
85 | .find(Filters.eq("userId", userId))
86 | .first()
87 | .get("userRole");
88 |
89 | if (userRole != null) {
90 | return UserRole.valueOf(userRole.toString());
91 |
92 | } else {
93 | return null;
94 | }
95 | }
96 |
97 | public static String getUserName(Long userId) {
98 | Object userNameObject = customerCollection
99 | .find(Filters.eq("userId", userId))
100 | .first()
101 | .get("userName");
102 |
103 | if (userNameObject != null) {
104 | return userNameObject.toString();
105 |
106 | } else {
107 | return null;
108 | }
109 | }
110 |
111 | public static String getUserPhoneNumber(Long userId) {
112 | Object userPhoneNumberObject = customerCollection
113 | .find(Filters.eq("userId", userId))
114 | .first()
115 | .get("userPhoneNumber");
116 |
117 | if (userPhoneNumberObject != null) {
118 | return CipherHelper.decrypt(userPhoneNumberObject.toString());
119 |
120 | } else {
121 | return null;
122 | }
123 | }
124 |
125 | public static String getUserTag(Long userId) {
126 | Object userTagObject = customerCollection
127 | .find(Filters.eq("userId", userId))
128 | .first()
129 | .get("userTag");
130 |
131 | if (userTagObject != null) {
132 | return CipherHelper.decrypt(userTagObject.toString());
133 |
134 | } else {
135 | return null;
136 | }
137 | }
138 |
139 | public static CountryCode getUserLocale(Long userId) {
140 | return CountryCode.valueOf(customerCollection
141 | .find(Filters.eq("userId", userId))
142 | .first()
143 | .get("userLocale")
144 | .toString());
145 | }
146 |
147 | public static String getIsPhoneNumberHidden(Long userId) {
148 | Object isPhoneNumberHidden = customerCollection.find(
149 | Filters.eq("userId", userId))
150 | .first()
151 | .get("isPhoneNumberHidden");
152 |
153 | if (isPhoneNumberHidden != null) {
154 | return isPhoneNumberHidden.toString();
155 |
156 | } else {
157 | return null;
158 | }
159 | }
160 |
161 | public static UserStatus getUserStatus(Long userId) {
162 | return UserStatus.valueOf(
163 | customerCollection.find(
164 | Filters.eq("userId", userId))
165 | .first()
166 | .get("userStatus")
167 | .toString());
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/parsers/CommandParser.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.parsers;
2 |
3 | import com.companerobot.keyboards.ReplyKeyboardHelper;
4 | import com.companerobot.misc.UserCollection;
5 |
6 | import org.telegram.telegrambots.meta.api.objects.User;
7 | import org.telegram.telegrambots.meta.api.objects.message.Message;
8 |
9 | import static com.companerobot.helpers.MessageExecutionHelper.sendMessageExecutor;
10 |
11 | public class CommandParser {
12 |
13 | public static void parseCommand(Message message) {
14 | User currentUser = message.getFrom();
15 | Long currentUserId = currentUser.getId();
16 |
17 | if (message.getText().equals("/start") && !UserCollection.isUserExist(currentUserId)) {
18 | UserCollection.addUserToDB(currentUserId);
19 | sendMessageExecutor(
20 | ReplyKeyboardHelper.chooseLanguageKeyboard(currentUserId)
21 | );
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/parsers/ContactParser.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.parsers;
2 |
3 | import com.companerobot.enums.CountryCode;
4 | import com.companerobot.enums.UserStatus;
5 | import com.companerobot.helpers.LocalizationHelper;
6 | import com.companerobot.helpers.RestrictionHelper;
7 | import com.companerobot.keyboards.ReplyKeyboardHelper;
8 | import com.companerobot.keyboards.UserManagementReplyKeyboards;
9 | import com.companerobot.misc.UserCollection;
10 | import org.telegram.telegrambots.meta.api.objects.message.Message;
11 |
12 | import static com.companerobot.constants.TextMessages.*;
13 | import static com.companerobot.constants.TextValues.*;
14 | import static com.companerobot.enums.UserStatus.*;
15 | import static com.companerobot.helpers.MessageExecutionHelper.sendMessageExecutor;
16 | import static com.companerobot.helpers.MessageExecutionHelper.sendMessageToUser;
17 |
18 | public class ContactParser {
19 |
20 | public static void parseContact(Message message) {
21 | Long currentUserId = message.getFrom().getId();
22 | CountryCode userLocale = UserCollection.getUserLocale(currentUserId);
23 | UserStatus userStatus = UserCollection.getUserStatus(currentUserId);
24 | String userPhoneNumber = message.getContact().getPhoneNumber();
25 |
26 | if (RestrictionHelper.isRestrictedPhoneNumber(userPhoneNumber)) {
27 | sendMessageToUser(currentUserId, LocalizationHelper.getValueByCode(RESTRICTED_PHONE_NUMBER_MESSAGE, userLocale));
28 | return;
29 | }
30 |
31 | if (userStatus == WAITING_USER_CONTACT) {
32 | addUserNumberAtRegistration(message, currentUserId, userLocale);
33 |
34 | } else if (userStatus == EDIT_PHONE_NUMBER) {
35 | addUserNumberAtEditing(message, currentUserId, userLocale);
36 | }
37 | }
38 |
39 |
40 | private static void addUserNumberAtRegistration(Message message, Long userId, CountryCode userLocale) {
41 | if (UserCollection.getUserName(userId) == null &&
42 | UserCollection.getUserPhoneNumber(userId) == null) {
43 |
44 | if (message.getContact().getUserId() == null || !message.getContact().getUserId().equals(message.getFrom().getId())) {
45 | sendMessageToUser(userId, LocalizationHelper.getValueByCode(INCORRECT_CONTACT_MESSAGE, userLocale));
46 | } else {
47 | String userName = message.getContact().getFirstName();
48 | String userPhoneNumber = message.getContact().getPhoneNumber();
49 | String userTag = message.getFrom().getUserName(); //.getUserName() - IT IS CORRECT ;)
50 |
51 | UserCollection.updateUserName(userId, userName);
52 | UserCollection.updateUserPhoneNumber(userId, userPhoneNumber);
53 | UserCollection.updateUserStatus(userId, WAITING_ROLE);
54 |
55 | sendMessageToUser(userId, LocalizationHelper.getValueByCode(MESSAGE_AFTER_REGISTRATION_WITH_PHONE_NUMBER, userLocale).formatted(userName));
56 | if (userTag == null) {
57 | sendMessageToUser(userId, LocalizationHelper.getValueByCode(MESSAGE_MISSING_USER_TAG_GENERAL, userLocale));
58 | } else {
59 | UserCollection.updateUserTag(userId, userTag);
60 | }
61 | sendMessageExecutor(
62 | ReplyKeyboardHelper.chooseRoleKeyboard(userId)
63 | );
64 | }
65 | }
66 | }
67 |
68 |
69 | private static void addUserNumberAtEditing(Message message, Long userId, CountryCode userLocale) {
70 | if (message.getContact().getUserId() == null || !message.getContact().getUserId().equals(message.getFrom().getId())) {
71 | sendMessageToUser(userId, LocalizationHelper.getValueByCode(INCORRECT_CONTACT_MESSAGE, userLocale));
72 | } else {
73 | String userPhoneNumber = message.getContact().getPhoneNumber();
74 | UserCollection.updateUserPhoneNumber(userId, userPhoneNumber);
75 | sendMessageToUser(userId, LocalizationHelper.getValueByCode(SUCCESSFUL_DATA_SAVED_MESSAGE, userLocale));
76 |
77 | String userName = UserCollection.getUserName(userId);
78 | String phoneNumber = UserCollection.getUserPhoneNumber(userId);
79 | if (phoneNumber == null) {
80 | phoneNumber = LocalizationHelper.getValueByCode(EMPTY_VALUE, userLocale);
81 | } else {
82 | phoneNumber = "+" + phoneNumber;
83 | }
84 |
85 | String isPhoneNumberHidden;
86 | if (Boolean.parseBoolean(UserCollection.getIsPhoneNumberHidden(userId))) {
87 | isPhoneNumberHidden = LocalizationHelper.getValueByCode(YES_VALUE, userLocale);
88 | } else {
89 | isPhoneNumberHidden = LocalizationHelper.getValueByCode(NO_VALUE, userLocale);
90 | }
91 |
92 | UserCollection.updateUserStatus(userId, IN_SETTINGS_MENU);
93 | sendMessageExecutor(
94 | UserManagementReplyKeyboards.openedSettingsKeyboard(userId,
95 | LocalizationHelper.getValueByCode(SHOW_ALL_USER_DATA_MESSAGE, userLocale).formatted(userName, phoneNumber, isPhoneNumberHidden))
96 | );
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/parsers/LocationParser.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.parsers;
2 |
3 | import com.companerobot.enums.CountryCode;
4 | import com.companerobot.enums.UserRole;
5 | import com.companerobot.helpers.LocalizationHelper;
6 | import com.companerobot.helpers.RestrictionHelper;
7 | import com.companerobot.misc.UserCollection;
8 | import org.telegram.telegrambots.meta.api.objects.message.Message;
9 |
10 | import static com.companerobot.constants.TextMessages.RESTRICTED_LOCATION_MESSAGE;
11 | import static com.companerobot.parsers.location_parsers.DriverLocationParser.parseDriverLocation;
12 | import static com.companerobot.parsers.location_parsers.PassengerLocationParser.parsePassengerLocation;
13 | import static com.companerobot.helpers.MessageExecutionHelper.sendMessageToUser;
14 |
15 | public class LocationParser {
16 |
17 | public static void parseLocation(Message message) {
18 |
19 | double latitude = message.getLocation().getLatitude();
20 | double longitude = message.getLocation().getLongitude();
21 | Long userId = message.getFrom().getId();
22 | CountryCode userLocale = UserCollection.getUserLocale(userId);
23 |
24 | if (RestrictionHelper.isRestrictedLocation(latitude, longitude)) {
25 | sendMessageToUser(userId, LocalizationHelper.getValueByCode(RESTRICTED_LOCATION_MESSAGE, userLocale));
26 | return;
27 | }
28 |
29 | UserRole userRole = UserCollection.getUserRole(userId);
30 |
31 | switch (userRole) {
32 | case PASSENGER:
33 | parsePassengerLocation(message);
34 | break;
35 | case DRIVER:
36 | parseDriverLocation(message);
37 | break;
38 | case null, default:
39 | break;
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/parsers/MessageParser.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.parsers;
2 |
3 | import com.companerobot.enums.UserRole;
4 | import com.companerobot.misc.UserCollection;
5 | import org.telegram.telegrambots.meta.api.objects.message.Message;
6 |
7 | import static com.companerobot.enums.UserRole.DRIVER;
8 | import static com.companerobot.enums.UserRole.PASSENGER;
9 | import static com.companerobot.parsers.message_parsers.DriverMessageParser.parseDriverMessage;
10 | import static com.companerobot.parsers.message_parsers.MiscMessageParser.parseMiscMessage;
11 | import static com.companerobot.parsers.message_parsers.PassengerMessageParser.parsePassengerMessage;
12 |
13 |
14 | public class MessageParser {
15 |
16 | public static void parseMessage(Message message) {
17 | UserRole userRole = UserCollection.getUserRole(message.getFrom().getId());
18 |
19 | if (userRole == PASSENGER) {
20 | parsePassengerMessage(message);
21 |
22 | } else if (userRole == DRIVER) {
23 | parseDriverMessage(message);
24 |
25 | // } else if (userRole == SUPER_ADMIN) {
26 | // parseSuperAdminMessage(message);
27 | } else {
28 | parseMiscMessage(message);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/parsers/QueryParser.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.parsers;
2 |
3 | import com.companerobot.enums.UserRole;
4 | import com.companerobot.misc.UserCollection;
5 | import org.telegram.telegrambots.meta.api.objects.Update;
6 |
7 | import static com.companerobot.enums.UserRole.DRIVER;
8 | import static com.companerobot.enums.UserRole.PASSENGER;
9 | import static com.companerobot.parsers.query_parsers.DriverQueryParser.parseDriverQuery;
10 | import static com.companerobot.parsers.query_parsers.PassengerQueryParser.parsePassengerQuery;
11 |
12 | public class QueryParser {
13 |
14 | public static void parseQuery(Update update) {
15 | UserRole userRole = UserCollection.getUserRole(update.getCallbackQuery().getFrom().getId());
16 |
17 | if (userRole == PASSENGER) {
18 | parsePassengerQuery(update);
19 |
20 | } else if (userRole == DRIVER) {
21 | parseDriverQuery(update);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/parsers/location_parsers/DriverLocationParser.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.parsers.location_parsers;
2 |
3 | import com.companerobot.enums.CountryCode;
4 | import com.companerobot.enums.DriverInfoFillingStatus;
5 | import com.companerobot.enums.OrderStatus;
6 | import com.companerobot.helpers.CipherHelper;
7 | import com.companerobot.helpers.LocalizationHelper;
8 | import com.companerobot.helpers.RoutingHelper;
9 | import com.companerobot.keyboards.InlineKeyboardHelper;
10 | import com.companerobot.keyboards.ReplyKeyboardHelper;
11 | import com.companerobot.misc.DriverCollection;
12 | import com.companerobot.misc.OrderCollection;
13 | import com.companerobot.misc.ReviewCollection;
14 | import com.companerobot.misc.UserCollection;
15 | import com.mongodb.client.model.geojson.Point;
16 | import com.mongodb.client.model.geojson.Position;
17 | import org.bson.Document;
18 | import org.json.JSONObject;
19 | import org.telegram.telegrambots.meta.api.objects.message.Message;
20 |
21 | import static com.companerobot.constants.HookMessages.*;
22 | import static com.companerobot.constants.TextMessages.*;
23 | import static com.companerobot.enums.DriverInfoFillingStatus.*;
24 | import static com.companerobot.enums.OrderStatus.DRIVER_ACCEPTED;
25 | import static com.companerobot.enums.OrderStatus.WAITING_DRIVER_LOCATION;
26 | import static com.companerobot.helpers.MessageExecutionHelper.*;
27 |
28 | public class DriverLocationParser {
29 |
30 | public static void parseDriverLocation(Message message) {
31 | Long driverId = message.getFrom().getId();
32 | CountryCode driverLocale = UserCollection.getUserLocale(driverId);
33 | Document order = OrderCollection.getUnfinishedOrderByDriverId(driverId);
34 |
35 | if (order != null) {
36 | parseDriverLocationInOrder(message, order, driverId, driverLocale);
37 | } else {
38 | parseDriverLocation(message, driverId, driverLocale);
39 | }
40 | }
41 |
42 |
43 | private static void parseDriverLocationInOrder(Message message, Document order, Long driverId, CountryCode driverLocale) {
44 | OrderStatus orderStatus = OrderStatus.valueOf(order.get("orderStatus").toString());
45 |
46 | if (orderStatus == WAITING_DRIVER_LOCATION) {
47 | sendLocationToPassenger(message, order, driverId, driverLocale);
48 | }
49 | }
50 |
51 |
52 | private static void parseDriverLocation(Message message, Long driverId, CountryCode driverLocale) {
53 | Document driverInfo = DriverCollection.getDriverInfoByDriverId(driverId);
54 | DriverInfoFillingStatus driverStatus = DriverInfoFillingStatus.valueOf(driverInfo.get("driverInfoFillingStatus").toString());
55 |
56 | if (driverStatus == WAITING_LOCATION) {
57 | setDriverLocationAtRegistration(message, driverId, driverLocale);
58 |
59 | } else if (driverStatus == INFO_IS_FILLED) {
60 | updateDriverLocation(message, driverId, driverLocale);
61 |
62 | }
63 | }
64 |
65 | private static void setDriverLocationAtRegistration(Message message, Long driverId, CountryCode driverLocale) {
66 | Point point = new Point(new Position(message.getLocation().getLongitude(), message.getLocation().getLatitude()));
67 | DriverCollection.setLocation(driverId, point);
68 | DriverCollection.setDriverInfoFillingStatus(driverId, INFO_IS_FILLED);
69 |
70 | sendMessageToUser(driverId, LocalizationHelper.getValueByCode(CAR_INFO_REGISTRATION_FINISHED_MESSAGE, driverLocale));
71 | DriverCollection.setIsWaitingForNewTrip(driverId, true);
72 | sendMessageExecutor(
73 | ReplyKeyboardHelper.mainMenuDriverHideOrdersKeyboard(driverId, LocalizationHelper.getValueByCode(STOP_SHIFT_MESSAGE, driverLocale)
74 | .formatted(LocalizationHelper.getValueByCode(STOP_WORK_SHIFT_HOOK_MESSAGE, driverLocale)))
75 | );
76 | }
77 |
78 |
79 | private static void updateDriverLocation(Message message, Long driverId, CountryCode driverLocale) {
80 | Point point = new Point(new Position(message.getLocation().getLongitude(), message.getLocation().getLatitude()));
81 | DriverCollection.setLocation(driverId, point);
82 |
83 | sendMessageToUser(driverId, LocalizationHelper.getValueByCode(SUCCESSFUL_DATA_SAVED_MESSAGE, driverLocale));
84 | }
85 |
86 |
87 | private static void sendLocationToPassenger(Message message, Document order, Long driverId, CountryCode driverLocale) {
88 | String currentDriverLocation = String.format("%s,%s", message.getLocation().getLongitude(), message.getLocation().getLatitude());
89 |
90 | String destinationAddressLatitude = CipherHelper.decrypt(order.get("destinationAddressLatitude").toString());
91 | String destinationAddressLongitude = CipherHelper.decrypt(order.get("destinationAddressLongitude").toString());
92 | String passengerPickupPoint = String.format("%s,%s", destinationAddressLongitude, destinationAddressLatitude);
93 |
94 | JSONObject tripData = RoutingHelper.getTripData(currentDriverLocation, passengerPickupPoint);
95 | double tripLengthToPassenger = RoutingHelper.getTripLengthInKilometers(tripData.getDouble("distance"));
96 | int estimationTime = RoutingHelper.getTripDurationInMinutes(tripData.getDouble("duration"));
97 |
98 | Long passengerId = Long.valueOf(order.get("userId").toString());
99 | CountryCode passengerLocale = UserCollection.getUserLocale(passengerId);
100 | sendMessageToUser(passengerId, LocalizationHelper.getValueByCode(DRIVER_LOCATION_MESSAGE, passengerLocale).formatted(tripLengthToPassenger, estimationTime));
101 | sendLocationToUser(passengerId, currentDriverLocation);
102 |
103 | OrderCollection.updateOrderStatus(order.get("orderId").toString(), DRIVER_ACCEPTED);
104 |
105 | String passengerName = UserCollection.getUserName(passengerId);
106 | String passengerPhoneNumber = UserCollection.getUserPhoneNumber(passengerId);
107 |
108 | String passengerUserTag = UserCollection.getUserTag(passengerId);
109 | boolean isPhoneNumberHidden = Boolean.parseBoolean(UserCollection.getIsPhoneNumberHidden(passengerId));
110 | int passengerReviewsAmount = ReviewCollection.getUserReviewsAmount(passengerId);
111 |
112 | StringBuilder passengerInfoMessage = new StringBuilder(LocalizationHelper.getValueByCode(LOCATION_SENT_TO_PASSENGER_MESSAGE, driverLocale))
113 | .append(LocalizationHelper.getValueByCode(PASSENGER_INFO_BASE_MESSAGE, driverLocale).formatted(passengerName));
114 |
115 | if (!isPhoneNumberHidden) {
116 | passengerInfoMessage.append(LocalizationHelper.getValueByCode(PHONE_NUMBER_MESSAGE, driverLocale).formatted(passengerPhoneNumber));
117 | }
118 |
119 | if (passengerReviewsAmount >= 10) {
120 | passengerInfoMessage.append(LocalizationHelper.getValueByCode(RATING_MESSAGE, driverLocale)
121 | .formatted(ReviewCollection.getUserRating(passengerId)));
122 | passengerInfoMessage.append(LocalizationHelper.getValueByCode(PASSENGER_INFO_REVIEWS_AMOUNT_MESSAGE, driverLocale).formatted(passengerReviewsAmount));
123 | }
124 |
125 | if (isPhoneNumberHidden && passengerUserTag == null) {
126 | passengerInfoMessage.append(LocalizationHelper.getValueByCode(PASSENGER_INFO_MISSING_CONTACTS_MESSAGE, driverLocale));
127 | }
128 |
129 | passengerInfoMessage.append(LocalizationHelper.getValueByCode(FINANCIAL_OPERATIONS_WARN_MESSAGE, driverLocale));
130 |
131 | if (passengerUserTag == null) {
132 | sendMessageToUser(driverId, passengerInfoMessage.toString());
133 | } else {
134 | sendMessageExecutor(
135 | InlineKeyboardHelper.passengerContactsMarkupKeyboard(driverId, passengerId, passengerInfoMessage.toString())
136 | );
137 | }
138 |
139 | sendMessageExecutor(ReplyKeyboardHelper.driverAcceptedOrderKeyboard(driverId, LocalizationHelper.getValueByCode(FUTURE_ARRIVAL_REMINDER_MESSAGE, driverLocale)
140 | .formatted(LocalizationHelper.getValueByCode(CONFIRM_ARRIVAL_HOOK_MESSAGE, driverLocale))));
141 | }
142 |
143 | }
144 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/parsers/location_parsers/PassengerLocationParser.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.parsers.location_parsers;
2 |
3 | import com.companerobot.enums.CountryCode;
4 | import com.companerobot.enums.OrderStatus;
5 | import com.companerobot.helpers.AddressHelper;
6 | import com.companerobot.helpers.CipherHelper;
7 | import com.companerobot.helpers.LocalizationHelper;
8 | import com.companerobot.helpers.RoutingHelper;
9 | import com.companerobot.keyboards.ReplyKeyboardHelper;
10 | import com.companerobot.misc.OrderCollection;
11 | import com.companerobot.misc.UserCollection;
12 | import org.bson.Document;
13 | import org.json.JSONObject;
14 | import org.telegram.telegrambots.meta.api.objects.message.Message;
15 |
16 | import static com.companerobot.constants.TextMessages.REQUEST_DESTINATION_POINT_PASSENGER_MESSAGE;
17 | import static com.companerobot.enums.OrderStatus.*;
18 | import static com.companerobot.helpers.MessageExecutionHelper.sendMessageExecutor;
19 | import static com.companerobot.helpers.MessageExecutionHelper.sendMessageToUser;
20 |
21 | public class PassengerLocationParser {
22 |
23 | public static void parsePassengerLocation(Message message) {
24 | Long passengerId = message.getFrom().getId();
25 | CountryCode passengerLocale = UserCollection.getUserLocale(passengerId);
26 | Document order = OrderCollection.getUnfinishedOrderByPassengerId(passengerId);
27 |
28 | if (order == null) {
29 | return;
30 | }
31 |
32 | OrderStatus orderStatus = OrderStatus.valueOf(order.get("orderStatus").toString());
33 |
34 | if (orderStatus == WAITING_PICKUP_ADDRESS) {
35 | setPickupPoint(message, passengerId, passengerLocale);
36 |
37 | } else if (orderStatus == WAITING_DESTINATION_ADDRESS) {
38 | setDestinationPoint(message, passengerId);
39 | }
40 |
41 | }
42 |
43 |
44 | private static void setPickupPoint(Message message, Long passengerId, CountryCode passengerLocale) {
45 | JSONObject pickupAddressResponse = AddressHelper.getAddressByCoordinates(message.getLocation().getLatitude(), message.getLocation().getLongitude(), 18);
46 | String orderId = OrderCollection.getOrderByPassengerIdAndStatus(passengerId, WAITING_PICKUP_ADDRESS).get("orderId").toString();
47 |
48 | OrderCollection.setPickUpAddressLatitude(orderId, message.getLocation().getLatitude());
49 | OrderCollection.setPickUpAddressLongitude(orderId, message.getLocation().getLongitude());
50 | OrderCollection.setPickUpAddress(orderId, pickupAddressResponse.getString("display_name"));
51 | OrderCollection.setCountryCode(orderId, CountryCode.valueOf(pickupAddressResponse.getJSONObject("address").getString("country_code").toUpperCase()));
52 |
53 | OrderCollection.updateOrderStatus(orderId, WAITING_DESTINATION_ADDRESS);
54 | sendMessageToUser(passengerId, LocalizationHelper.getValueByCode(REQUEST_DESTINATION_POINT_PASSENGER_MESSAGE, passengerLocale));
55 | }
56 |
57 |
58 | private static void setDestinationPoint(Message message, Long passengerId) {
59 | JSONObject destinationAddressResponse = AddressHelper.getAddressByCoordinates(message.getLocation().getLatitude(), message.getLocation().getLongitude(), 18);
60 | Document order = OrderCollection.getOrderByPassengerIdAndStatus(passengerId, WAITING_DESTINATION_ADDRESS);
61 | String orderId = order.get("orderId").toString();
62 |
63 | String destinationLocationCoordinates = String.format("%s,%s", message.getLocation().getLongitude(), message.getLocation().getLatitude());
64 | OrderCollection.setDestinationAddressLongitude(orderId, message.getLocation().getLongitude());
65 | OrderCollection.setDestinationAddressLatitude(orderId, message.getLocation().getLatitude());
66 | OrderCollection.setDestinationAddress(orderId, destinationAddressResponse.getString("display_name"));
67 |
68 | OrderCollection.setApproximateDestinationAddress(orderId,
69 | AddressHelper.getAddressByCoordinates(
70 | message.getLocation().getLatitude(),
71 | message.getLocation().getLongitude(), 12).getString("display_name"));
72 |
73 | String pickUpAddressLatitude = CipherHelper.decrypt(order.get("pickUpAddressLatitude").toString());
74 | String pickUpAddressLongitude = CipherHelper.decrypt(order.get("pickUpAddressLongitude").toString());
75 | String pickupLocationCoordinates = String.format("%s,%s", pickUpAddressLongitude, pickUpAddressLatitude);
76 |
77 | JSONObject tripData = RoutingHelper.getTripData(pickupLocationCoordinates, destinationLocationCoordinates);
78 | double tripLength = RoutingHelper.getTripLengthInKilometers(tripData.getDouble("distance"));
79 | OrderCollection.setTripLength(orderId, tripLength);
80 | OrderCollection.updateOrderStatus(orderId, WAITING_IF_NOTES_NEEDED);
81 |
82 | sendMessageExecutor(
83 | ReplyKeyboardHelper.passengerNotesRequestKeyboard(passengerId)
84 | );
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/parsers/message_parsers/MiscMessageParser.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.parsers.message_parsers;
2 |
3 | import com.companerobot.enums.CountryCode;
4 | import com.companerobot.enums.UserStatus;
5 | import com.companerobot.helpers.LocalizationHelper;
6 | import com.companerobot.keyboards.ReplyKeyboardHelper;
7 | import com.companerobot.misc.DriverCollection;
8 | import com.companerobot.misc.ReviewCollection;
9 | import com.companerobot.misc.UserCollection;
10 | import org.telegram.telegrambots.meta.api.objects.message.Message;
11 |
12 | import static com.companerobot.constants.HookMessages.*;
13 | import static com.companerobot.constants.TextMessages.*;
14 | import static com.companerobot.constants.URLs.*;
15 | import static com.companerobot.enums.CountryCode.*;
16 | import static com.companerobot.enums.UserRole.DRIVER;
17 | import static com.companerobot.enums.UserRole.PASSENGER;
18 | import static com.companerobot.enums.UserStatus.*;
19 | import static com.companerobot.helpers.MessageExecutionHelper.sendMessageExecutor;
20 | import static com.companerobot.helpers.MessageExecutionHelper.sendMessageToUser;
21 |
22 | public class MiscMessageParser {
23 |
24 | public static void parseMiscMessage(Message message) {
25 | Long userId = message.getFrom().getId();
26 | CountryCode userLocale = UserCollection.getUserLocale(userId);
27 | UserStatus userStatus = UserCollection.getUserStatus(userId);
28 |
29 | String messageText = message.getText();
30 | String localizedSkipShareMyContact = LocalizationHelper.getValueByCode(SKIP_SHARE_MY_CONTACT_HOOK_MESSAGE, userLocale);
31 | String localizedAuthorizeAsPassenger = LocalizationHelper.getValueByCode(AUTHORIZE_AS_PASSENGER_HOOK_MESSAGE, userLocale);
32 | String localizedAuthorizeAsDriver = LocalizationHelper.getValueByCode(AUTHORIZE_AS_DRIVER_HOOK_MESSAGE, userLocale);
33 |
34 | if (messageText.equals(CHOOSE_ENGLISH_LANGUAGE_HOOK_MESSAGE)) {
35 | chooseEnglishLanguage(userId, userStatus);
36 |
37 | } else if (messageText.equals(CHOOSE_SPANISH_LANGUAGE_HOOK_MESSAGE)) {
38 | chooseSpanishLanguage(userId, userStatus);
39 |
40 | } else if (messageText.equals(CHOOSE_UKRAINIAN_LANGUAGE_HOOK_MESSAGE)) {
41 | chooseUkrainianLanguage(userId, userStatus);
42 |
43 | } else if (messageText.equals(CHOOSE_PORTUGUESE_LANGUAGE_HOOK_MESSAGE)) {
44 | choosePortugueseLanguage(userId, userStatus);
45 |
46 | } else if (messageText.equals(CHOOSE_GERMAN_LANGUAGE_HOOK_MESSAGE)) {
47 | chooseGermanLanguage(userId, userStatus);
48 |
49 | } else if (messageText.equals(CHOOSE_FRENCH_LANGUAGE_HOOK_MESSAGE)) {
50 | chooseFrenchLanguage(userId, userStatus);
51 |
52 | } else if (messageText.equals(localizedSkipShareMyContact)) {
53 | skipShareMyContact(message, userId, userStatus, userLocale);
54 |
55 | } else if (messageText.equals(localizedAuthorizeAsPassenger)) {
56 | authorizeAsPassenger(userId, userStatus, userLocale);
57 |
58 | } else if (messageText.equals(localizedAuthorizeAsDriver)) {
59 | authorizeAsDriver(userId, userStatus, userLocale);
60 | }
61 | }
62 |
63 |
64 | private static void chooseEnglishLanguage(Long userId, UserStatus userStatus) {
65 | if (userStatus == WAITING_USER_LOCALIZATION) {
66 | UserCollection.updateUserLocalization(userId, US);
67 | UserCollection.updateUserStatus(userId, WAITING_USER_CONTACT);
68 | sendMessageToUser(userId, String.format(
69 | LocalizationHelper.getValueByCode(USER_POLICY_AGREEMENT_MESSAGE, US),
70 | USER_POLICY_AGREEMENT_ENG_URL,
71 | PRIVACY_POLICY_ENG_URL));
72 | sendMessageExecutor(
73 | ReplyKeyboardHelper.requestContactWithButton(userId, LocalizationHelper.getValueByCode(REQUEST_CONTACTS_MESSAGE, US))
74 | );
75 | }
76 | }
77 |
78 |
79 | private static void chooseUkrainianLanguage(Long userId, UserStatus userStatus) {
80 | if (userStatus == WAITING_USER_LOCALIZATION) {
81 | UserCollection.updateUserLocalization(userId, UA);
82 | UserCollection.updateUserStatus(userId, WAITING_USER_CONTACT);
83 | sendMessageToUser(userId, String.format(
84 | LocalizationHelper.getValueByCode(USER_POLICY_AGREEMENT_MESSAGE, UA),
85 | USER_POLICY_AGREEMENT_UA_URL,
86 | PRIVACY_POLICY_UA_URL));
87 | sendMessageExecutor(
88 | ReplyKeyboardHelper.requestContactWithButton(userId, LocalizationHelper.getValueByCode(REQUEST_CONTACTS_MESSAGE, UA))
89 | );
90 | }
91 | }
92 |
93 |
94 | private static void chooseSpanishLanguage(Long userId, UserStatus userStatus) {
95 | if (userStatus == WAITING_USER_LOCALIZATION) {
96 | UserCollection.updateUserLocalization(userId, ES);
97 | UserCollection.updateUserStatus(userId, WAITING_USER_CONTACT);
98 | sendMessageToUser(userId, String.format(
99 | LocalizationHelper.getValueByCode(USER_POLICY_AGREEMENT_MESSAGE, ES),
100 | USER_POLICY_AGREEMENT_ES_URL,
101 | PRIVACY_POLICY_ES_URL));
102 | sendMessageExecutor(
103 | ReplyKeyboardHelper.requestContactWithButton(userId, LocalizationHelper.getValueByCode(REQUEST_CONTACTS_MESSAGE, ES))
104 | );
105 | }
106 | }
107 |
108 |
109 | private static void choosePortugueseLanguage(Long userId, UserStatus userStatus) {
110 | if (userStatus == WAITING_USER_LOCALIZATION) {
111 | UserCollection.updateUserLocalization(userId, PT);
112 | UserCollection.updateUserStatus(userId, WAITING_USER_CONTACT);
113 | sendMessageToUser(userId, String.format(
114 | LocalizationHelper.getValueByCode(USER_POLICY_AGREEMENT_MESSAGE, PT),
115 | USER_POLICY_AGREEMENT_PT_URL,
116 | PRIVACY_POLICY_PT_URL));
117 | sendMessageExecutor(
118 | ReplyKeyboardHelper.requestContactWithButton(userId, LocalizationHelper.getValueByCode(REQUEST_CONTACTS_MESSAGE, PT))
119 | );
120 | }
121 | }
122 |
123 |
124 | private static void chooseGermanLanguage(Long userId, UserStatus userStatus) {
125 | if (userStatus == WAITING_USER_LOCALIZATION) {
126 | UserCollection.updateUserLocalization(userId, DE);
127 | UserCollection.updateUserStatus(userId, WAITING_USER_CONTACT);
128 | sendMessageToUser(userId, String.format(
129 | LocalizationHelper.getValueByCode(USER_POLICY_AGREEMENT_MESSAGE, DE),
130 | USER_POLICY_AGREEMENT_DE_URL,
131 | PRIVACY_POLICY_DE_URL));
132 | sendMessageExecutor(
133 | ReplyKeyboardHelper.requestContactWithButton(userId, LocalizationHelper.getValueByCode(REQUEST_CONTACTS_MESSAGE, DE))
134 | );
135 | }
136 | }
137 |
138 |
139 | private static void chooseFrenchLanguage(Long userId, UserStatus userStatus) {
140 | if (userStatus == WAITING_USER_LOCALIZATION) {
141 | UserCollection.updateUserLocalization(userId, FR);
142 | UserCollection.updateUserStatus(userId, WAITING_USER_CONTACT);
143 | sendMessageToUser(userId, String.format(
144 | LocalizationHelper.getValueByCode(USER_POLICY_AGREEMENT_MESSAGE, FR),
145 | USER_POLICY_AGREEMENT_FR_URL,
146 | PRIVACY_POLICY_FR_URL));
147 | sendMessageExecutor(
148 | ReplyKeyboardHelper.requestContactWithButton(userId, LocalizationHelper.getValueByCode(REQUEST_CONTACTS_MESSAGE, FR))
149 | );
150 | }
151 | }
152 |
153 |
154 | private static void skipShareMyContact(Message message, Long userId, UserStatus userStatus, CountryCode driverLocale) {
155 | if (userStatus == WAITING_USER_CONTACT) {
156 | String userName = message.getFrom().getFirstName();
157 | String userTag = message.getFrom().getUserName(); //.getUserName() - IT IS CORRECT ;)
158 | UserCollection.updateUserName(userId, userName);
159 | UserCollection.updateUserStatus(userId, WAITING_ROLE);
160 |
161 | if (userTag == null) {
162 | sendMessageToUser(userId, LocalizationHelper.getValueByCode(MESSAGE_AFTER_REGISTRATION_WITHOUT_PHONE_NUMBER, driverLocale));
163 | sendMessageToUser(userId, LocalizationHelper.getValueByCode(MESSAGE_MISSING_USER_TAG_GENERAL, driverLocale));
164 | sendMessageExecutor(
165 | ReplyKeyboardHelper.chooseRoleKeyboard(userId)
166 | );
167 | } else {
168 | UserCollection.updateUserTag(userId, userTag);
169 | sendMessageToUser(userId, LocalizationHelper.getValueByCode(MESSAGE_AFTER_REGISTRATION_WITHOUT_PHONE_NUMBER, driverLocale));
170 | sendMessageExecutor(
171 | ReplyKeyboardHelper.chooseRoleKeyboard(userId)
172 | );
173 | }
174 | }
175 | }
176 |
177 |
178 | private static void authorizeAsPassenger(Long userId, UserStatus userStatus, CountryCode driverLocale) {
179 | if (userStatus == WAITING_ROLE) {
180 | UserCollection.updateUserRole(userId, PASSENGER);
181 | UserCollection.updateUserStatus(userId, ACTIVE);
182 | ReviewCollection.addNewUserToReviewDB(userId);
183 |
184 | sendMessageExecutor(ReplyKeyboardHelper.mainMenuPassengerKeyboard(userId,
185 | LocalizationHelper.getValueByCode(PASSENGER_ROLE_WELCOME_MESSAGE, driverLocale)
186 | .formatted(LocalizationHelper.getValueByCode(CREATE_NEW_ORDER_HOOK_MESSAGE, driverLocale))));
187 | }
188 | }
189 |
190 |
191 | private static void authorizeAsDriver(Long userId, UserStatus userStatus, CountryCode driverLocale) {
192 | if (userStatus == WAITING_ROLE) {
193 | UserCollection.updateUserRole(userId, DRIVER);
194 | UserCollection.updateUserStatus(userId, ACTIVE);
195 | DriverCollection.addDriverToDB(userId);
196 | ReviewCollection.addNewUserToReviewDB(userId);
197 |
198 | sendMessageExecutor(
199 | ReplyKeyboardHelper.removeKeyboardForUser(userId, LocalizationHelper.getValueByCode(CAR_MODEL_REQUEST_MESSAGE, driverLocale))
200 | );
201 | }
202 | }
203 |
204 | }
205 |
--------------------------------------------------------------------------------
/src/main/java/com/companerobot/parsers/query_parsers/PassengerQueryParser.java:
--------------------------------------------------------------------------------
1 | package com.companerobot.parsers.query_parsers;
2 |
3 | import com.companerobot.enums.CountryCode;
4 | import com.companerobot.helpers.LocalizationHelper;
5 | import com.companerobot.helpers.MessageExecutionHelper;
6 | import com.companerobot.keyboards.ReplyKeyboardHelper;
7 | import com.companerobot.misc.OrderCollection;
8 | import com.companerobot.misc.ReviewCollection;
9 | import com.companerobot.misc.UserCollection;
10 | import org.bson.Document;
11 | import org.telegram.telegrambots.meta.api.objects.Update;
12 | import org.telegram.telegrambots.meta.api.objects.message.MaybeInaccessibleMessage;
13 |
14 | import static com.companerobot.constants.Callbacks.*;
15 | import static com.companerobot.constants.TextMessages.*;
16 | import static com.companerobot.enums.OrderStatus.PASSENGER_CONFIRMATION_WAITING;
17 | import static com.companerobot.enums.OrderStatus.WAITING_DEPARTURE_DETAILS;
18 | import static com.companerobot.helpers.MessageExecutionHelper.sendMessageExecutor;
19 |
20 | public class PassengerQueryParser {
21 |
22 | public static void parsePassengerQuery(Update update) {
23 | String callbackData = update.getCallbackQuery().getData();
24 | String messageText = update.getCallbackQuery().getMessage().toString();
25 | Long passengerId = update.getCallbackQuery().getFrom().getId();
26 | CountryCode passengerLocale = UserCollection.getUserLocale(passengerId);
27 |
28 | if (callbackData.equals(ADD_POSTPONED_DEPARTURE_DETAILS_CALLBACK)) {
29 | addDepartureDetails(update);
30 |
31 | } else if (callbackData.equals(LIKE_RIDE_CALLBACK)) {
32 | addReviewOnDriver(update, messageText, passengerId, passengerLocale, true);
33 |
34 | } else if (callbackData.equals(DISLIKE_RIDE_CALLBACK)) {
35 | addReviewOnDriver(update, messageText, passengerId, passengerLocale, false);
36 | }
37 | }
38 |
39 |
40 | private static void addDepartureDetails(Update update) {
41 | Long passengerId = update.getCallbackQuery().getFrom().getId();
42 | CountryCode passengerLocale = UserCollection.getUserLocale(passengerId);
43 |
44 | Document order = OrderCollection.getOrderByPassengerIdAndStatus(passengerId, PASSENGER_CONFIRMATION_WAITING);
45 | OrderCollection.updateOrderStatus(order.get("orderId").toString(), WAITING_DEPARTURE_DETAILS);
46 |
47 | sendMessageExecutor(
48 | ReplyKeyboardHelper.backToPreviousPageKeyboard(passengerId, LocalizationHelper.getValueByCode(DEPARTURE_DETAILS_MESSAGE, passengerLocale))
49 | );
50 | }
51 |
52 | private static void addReviewOnDriver(Update update, String messageText, Long passengerId, CountryCode passengerLocale, boolean isLiked) {
53 | MaybeInaccessibleMessage message = update.getCallbackQuery().getMessage();
54 |
55 | String orderId = messageText.substring(
56 | messageText.indexOf(LocalizationHelper.getValueByCode(ORDER_ID_PART_MESSAGE, passengerLocale))
57 | + LocalizationHelper.getValueByCode(ORDER_ID_PART_MESSAGE, passengerLocale).length(),
58 | messageText.indexOf("\n"));
59 |
60 |
61 | Document order = OrderCollection.getOrderByOrderId(orderId);
62 | Long driverId = Long.valueOf(order.get("driverId").toString());
63 |
64 | ReviewCollection.addUserReview(driverId, passengerId, isLiked);
65 | MessageExecutionHelper.editMessage(message, LocalizationHelper.getValueByCode(AFTER_RATE_MESSAGE, passengerLocale));
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/resources/execution.properties:
--------------------------------------------------------------------------------
1 | bot_token=
2 | mongodb_client_url=
3 | cipher_algorithm=
4 | cipher_key=
--------------------------------------------------------------------------------
/src/main/resources/localization_de_DE.properties:
--------------------------------------------------------------------------------
1 | #HOOK MESSAGES
2 | authorize.as.passenger.hook.message = Fahrgast
3 | authorize.as.driver.hook.message = Fahrer
4 | confirm.arrival.hook.message = Ich bin angekommen
5 | create.new.order.hook.message = Starte eine Fahrersuche
6 | cancel.order.hook.message = Fahrt abbrechen
7 | finish.order.hook.message = Fahrt beenden
8 | share.location.hook.message = Standort teilen
9 | update.location.hook.message = Standort aktualisieren
10 | start.work.shift.hook.message = Starte eine Fahrgastsuche
11 | stop.work.shift.hook.message = Beende eine Fahrgastsuche
12 | share.my.contact.hook.message = Meine Kontaktdaten teilen
13 | skip.share.my.contact.hook.message = Schritt überspringen
14 | add.notes.hook.message = Ja, ich habe besondere Hinweise
15 | skip.notes.hook.message = Nein, habe ich nicht
16 | recommended.price.hook.message = %.2f
17 | confirm.order.hook.message = Bestätigen
18 | free.ride.hook.message = Kostenlose Fahrt
19 | confirm.postponed.order.hook.message = Die Fahrt wurde vereinbart
20 | decline.postponed.order.hook.message = Die Fahrt wurde nicht vereinbart
21 |
22 | #USER SETTINGS HOOK MESSAGES
23 | open.settings.hook.message = Einstellungen
24 | get.support.hook.message = Support
25 | exit.settings.hook.message = Einstellungen verlassen
26 | back.to.previous.page.hook.message = Zurück
27 | edit.user.name.hook.message = Namen ändern
28 | edit.phone.number.hook.message = Telefonnummer ändern
29 | remove.phone.number.hook.message = Telefonnummer entfernen
30 | edit.share.phone.number.hook.message = Datenschutz für Telefonnummer ändern
31 | reveal.phone.number.hook.message = Telefonnummer anzeigen
32 | hide.phone.number.hook.message = Telefonnummer verbergen
33 |
34 |
35 | #INLINE TEXT
36 | write.to.passenger.inline.text = Chat mit Fahrgast öffnen
37 | write.to.driver.inline.text = Chat mit Fahrer öffnen
38 | accept.inline.text = Akzeptieren
39 | open.pickup.point.inline.text = Abholpunkt auf der Karte öffnen
40 | open.destination.point.inline.text = Zielort auf der Karte öffnen
41 | add.postponed.departure.details.inline.text = Abfahrtszeit ändern
42 | wallet.inline.text=Brieftasche
43 |
44 |
45 | #MESSAGES
46 | user.policy.agreement.message = HINWEIS: Indem Sie CompaneroBot nutzen, erkennen Sie an, dass Sie diese Nutzungsbedingungen und die Datenschutzrichtlinie gelesen haben und damit einverstanden sind.
47 | request.contacts.message = Lasst uns kennenlernen!\n\nWenn Sie möchten, können Sie Ihre Telefonnummer teilen oder diesen Schritt überspringen.\n\nKeine dieser Optionen wird Ihre Erfahrung beeinträchtigen\uD83D\uDE09
48 | message.after.registration.with.phone.number = %s... Aufgeschrieben... Sie haben einen schönen Namen! Schön, Sie kennenzulernen!
49 | message.after.registration.without.phone.number = Kein Problem! Sie können es jederzeit selbst hinzufügen.
50 | message.missing.user.tag.general=Ein wenig mehr Aufmerksamkeit: \nWir respektieren Ihre Privatsphäre, aber wir müssen Sie darauf hinweisen, dass aufgrund des Fehlens eines Benutzernamens (der mit "@") in Ihrem Telegram-Profil und des Fehlens einer Telefonnummer der Fahrer oder Fahrgast Sie direkt kontaktieren können, wenn nötig.\n\nWir fordern Sie nicht auf, irgendetwas davon hinzuzufügen, wir warnen Sie nur\uD83D\uDE09
51 | missing.user.tag.without.number.passenger.warn.message=Ein wenig mehr Aufmerksamkeit: \nWir respektieren Ihre Privatsphäre, aber wir müssen Sie darauf hinweisen, dass aufgrund des Fehlens eines Benutzernamens (der mit "@") in Ihrem Telegram-Profil und des Fehlens einer Telefonnummer der Fahrer Sie nicht direkt kontaktieren kann, wenn nötig.\n\nWir fordern Sie nicht auf, irgendetwas davon hinzuzufügen, wir warnen Sie nur\uD83D\uDE09
52 | missing.user.tag.without.number.driver.warn.message=Ein wenig mehr Aufmerksamkeit: \nWir respektieren Ihre Privatsphäre, aber wir müssen Sie darauf hinweisen, dass aufgrund des Fehlens eines Benutzernamens (der mit "@") in Ihrem Telegram-Profil und des Fehlens einer Telefonnummer der Fahrgast Sie nicht direkt kontaktieren kann, wenn nötig.\n\nWir fordern Sie nicht auf, irgendetwas davon hinzuzufügen, wir warnen Sie nur\uD83D\uDE09
53 | incorrect.contact.message = Es scheint, dass der empfangene Kontakt nicht zu Ihnen gehört.
54 | choose.role.message = Wählen wir jetzt Ihre Rolle! Wen möchten Sie sein?
55 | phone.number.message=\nTelefonnummer: +%s
56 | rating.message=\nBewertung: %s/10
57 | financial.operations.warn.message=\n\nACHTUNG: Wir greifen in keiner Weise in finanzielle Transaktionen zwischen dem Fahrer und dem Fahrgast ein, die Frage der Zahlung und deren Methode wird von den Parteien unabhängig entschieden!
58 | departure.time.order.message=\nAbfahrtszeit: %s
59 | order.price.message=\nPreis: %.2f %s
60 | order.free.ride.message=\nDiese Fahrt ist KOSTENLOS
61 | further.contacts.postponed.message=\n\nDu musst nur alle Details direkt vereinbaren.
62 | after.rate.message=Danke für dein meinung! \u2764\uFE0F
63 | restricted.location.message=Es sieht so aus, als ob wir in dieser Region nicht tätig sind. Bitte wählen Sie eine andere aus.
64 | restricted.phone.number.message=Es sieht so aus, als ob Sie eine Telefonnummer aus einer eingeschränkten Region haben.\n\nBitte registrieren Sie sich mit einer anderen Telefonnummer, um vollen Zugriff auf die Funktionen zu erhalten.
65 |
66 | #PASSENGER MESSAGES
67 | passenger.role.welcome.message = Okie-Dokie!\n\nWenn Sie eine Fahrt möchten, drücken Sie bitte die "%s" Taste.
68 | request.pickup.point.passenger.message=Sicher! Wo befinden Sie sich?\n\nWie man den Standort übermittelt: \uD83D\uDCCE (Anlagensymbol) -> "Ort" -> Abholpunkt auf der Karte wählen
69 | request.destination.point.passenger.message=Wohin möchten Sie gehen?\n\nWie man den Standort übermittelt: \uD83D\uDCCE (Anlagensymbol) -> "Ort" -> Zielpunkt auf der Karte wählen
70 | ask.if.notes.needed.message = Erledigt. Haben Sie irgendwelche Hinweise für den Fahrer?
71 | add.notes.message = Sicher. Was kann der Fahrer für Sie tun?
72 | add.price.order.message = Laut unserer Berechnung beträgt die empfohlene Kosten für die Fahrt %.2f %s.\nSie können Ihren eigenen Preis in lokaler Währung angeben, indem Sie ihn direkt im Chat schreiben (zum Beispiel "5" oder "5.50").\n\nAber wenn Sie es sich nicht leisten können, klicken Sie auf den "Gratis Fahrt" Knopf ;)
73 | price.error.more.than.int.max.message = Leider haben Sie mehr als die maximal zulässigen Kosten für eine Fahrt angegeben.
74 | price.error.less.than.0.message = Tut mir leid, aber Sie können keinen negativen Betrag angeben :)
75 | price.error.other.message = Hoppla... Etwas ist schief gelaufen. Senden Sie mir den Preis im Format wie im Beispiel: "5" oder "5.50"
76 | confirmation.reminder.message = Wenn alles korrekt ist, können Sie es bestätigen ;)
77 | confirm.order.by.passenger.message = Die Fahrtanfrage wurde erstellt und an andere Fahrer gesendet!\n\nWenn ein Fahrer gefunden wird - ich lasse es Sie wissen ;)
78 | further.steps.for.passenger.postponed.message = Wenn Sie sich mit dem Fahrer einig sind, drücken Sie die "%s" Taste, oder drücken Sie "%s", wenn Sie einen anderen benötigen.
79 | cancel.trip.by.passenger.self.message = Ihre Fahrt wurde abgesagt!\n\nWenn Sie eine neue Fahrt möchten, drücken Sie bitte die "%s" Taste.
80 | driver.arrived.passenger.message = Ihr Fahrer ist angekommen und wartet auf Sie!
81 | finished.order.passenger.message = Ihre Fahrt ist beendet!\n\nWenn Sie eine neue Fahrt möchten, drücken Sie bitte die "%s" Taste.
82 | cancel.trip.by.driver.message = Ihre Fahrt wurde vom Fahrer abgesagt! Tut uns leid!\n\nAber wir haben Ihre Fahrtanfrage bereits an andere Fahrer gesendet ;)
83 | declined.postponed.trip.for.passenger.message = Wie schade, dass Sie keine Fahrt mit dem Fahrer arrangieren konnten :c\n\nAber wir haben Ihre Fahrtanfrage bereits an andere Fahrer gesendet ;)
84 | confirmed.postponed.trip.for.passenger.message = Sie haben Ihre Fahrt vereinbart, super! Jetzt können Sie direkt mit dem Fahrer über weitere Schritte kommunizieren.\n\nWenn Sie eine neue Fahrt möchten, drücken Sie bitte die "%s" Taste.
85 | add.review.on.driver.for.passengers.message=Bestell-ID: %s\nBitte erzählen Sie uns, wie Ihre Fahrt mit dem Fahrer verlaufen ist?
86 | confirmation.passenger.order.base.message=Bitte überprüfen Sie Ihre Reisedaten:\nAbholort: %s\nZielort: %s\nBemerkungen: %s
87 | driver.info.base.message=Ich habe den besten Fahrer für dich gefunden!\n\nName: %s
88 | driver.info.car.plate.message=\nAuto: %s, %s, %s
89 | driver.info.car.plate.postponed.message=\nAuto: %s
90 | driver.info.reviews.amount.message=\nAnzahl der Bewertungen für einen Fahrer: %s
91 | driver.info.missing.contacts.message=\n\nLeider hat der Fahrer beschlossen, seine Kontaktdaten nicht anzugeben. Er kann dich jedoch kontaktieren, wenn deine Kontaktdaten nicht versteckt sind.
92 | driver.info.location.message=\n\nDer Fahrer wird dir in Kürze seinen Standort mitteilen!
93 | payment.reminder.message=Bitte vergessen Sie nicht, die Fahrt nach deren Ende zu bezahlen.\nZu zahlen: %.2f %s.\n\nWenn Sie möchten, können Sie das Krypto-Wallet in Telegram verwenden, um dem Fahrer Geld zu überweisen.
94 |
95 | #DRIVER MESSAGES
96 | request.driver.location.message = Bitte teilen Sie Ihre Position mit einem Fahrgast über den "%s" Button!
97 | unavailable.order.message = Leider ist diese Fahrtanfrage nicht mehr verfügbar. Bitte wählen Sie eine andere.
98 | has.already.order.error.message = Es tut uns leid, aber es scheint, dass Sie bereits unfertige Fahrten haben. Bitte akzeptieren Sie neue Fahrten erst, nachdem Sie Ihre aktuellen beendet haben.
99 | order.id.part.message = Bestell-ID:
100 | car.model.request.message = Möchten Sie Fahrer werden? Cool! Erzählen Sie bitte, welches Modell Ihr Auto ist?
101 | driver.location.message = Ihr Fahrer befindet sich %s km von Ihrem Abholpunkt entfernt :)\n\nUngefähre Ankunftszeit: %d min
102 | further.steps.for.driver.postponed.message = Wenn Sie die Fahrt mit dem Fahrgast vereinbart haben, drücken Sie den "%s" Knopf, oder drücken Sie "%s", wenn dieser Auftrag Ihnen nicht zusagt.
103 | future.arrival.reminder.message = Wenn Sie am Abholpunkt sind, drücken Sie bitte den "%s" Knopf!
104 | cancel.trip.by.passenger.message = Ihre Fahrt wurde vom Fahrgast storniert! Das tut uns leid!\n\nJetzt werden Sie neue Angebote erhalten :)
105 | stop.shift.message = Wenn Sie die Suche nach einem Fahrgast stoppen möchten, drücken Sie den "%s" Knopf
106 | start.shift.message = Wenn Sie die Suche nach einem Fahrgast beginnen möchten, drücken Sie den "%s" Knopf
107 | car.color.request.message = Schönes Auto! Welche Farbe hat es?
108 | car.plate.number.request.message = Tolle Farbe! Welche Nummernschildnummer haben Sie darauf?
109 | driver.location.request.message=Das Letzte, bitte senden Sie mir einen Punkt auf der Karte, wo Sie Fahrgastanfragen erhalten möchten.\n\nSie werden Fahrtanfragen in einem Bereich von 25 km um Sie für sofortige Fahrten und 125 km um Sie für Fahrten, die im Voraus angefordert werden, erhalten.\n\nDrücke einfach die Taste "%s" oder sende den Standort, den du brauchst. Auf jeden Fall kannst du ihn später aktualisieren, falls nötig ;)
110 | car.info.registration.finished.message=Ok, wir sind fertig mit der Registrierung! Glückwunsch!\n\nJetzt werden Sie hier neue Fahranfragen von Fahrgästen erhalten.
111 | destination.point.driver.message = Der Fahrgast wurde benachrichtigt, dass Sie angekommen sind!\n\nIhr Zielort: %s\n\nSie können ihn auf der Karte mit dem Knopf unten öffnen ;)
112 | future.finish.order.reminder.message = Wenn Sie am Zielort sind, drücken Sie bitte den "%s" Knopf :)
113 | finished.order.driver.message = Ihre Fahrt ist beendet!\n\nJetzt werden Sie neue Angebote erhalten :)
114 | cancel.trip.by.driver.self.message = Ihre Fahrt wurde storniert!\n\nJetzt werden Sie neue Angebote erhalten :)
115 | declined.postponed.trip.for.driver.message = Wie schade, dass Sie keine Fahrt mit einem Fahrgast arrangieren konnten :c\n\nAber keine Sorge, Sie werden bald neue Angebote erhalten!
116 | confirmed.postponed.trip.for.driver.message = Sie haben Ihre Fahrt vereinbart, cool! Jetzt können Sie direkt mit dem Fahrgast über weitere Schritte kommunizieren.\n\nUnd jetzt werden Sie neue Angebote erhalten!
117 | departure.details.message = Wenn Sie ein Auto für ein bestimmtes Datum und eine bestimmte Zeit benötigen, geben Sie bitte diese Details hier an \uD83D\uDE4F
118 | add.review.on.passenger.for.drivers.message=Bestell-ID: %s\nBitte erzählen Sie uns, wie Ihre Reise mit dem Passagier verlaufen ist?
119 | new.order.base.message=Bestell-ID: %s\nAbholung: %s\nUngefähres Ziel: %s\nReiselänge: %s Km\nBemerkungen: %s
120 | location.sent.to.passenger.message=Dein Standort wurde an den Fahrgast gesendet, danke!
121 | passenger.info.base.message=Hier sind einige Informationen über deinen Fahrgast:\n\nName: %s
122 | passenger.info.missing.contacts.message=\n\nLeider hat der Fahrgast beschlossen, seine Kontaktdaten nicht anzugeben. Er kann dich jedoch kontaktieren, wenn deine Kontaktdaten nicht versteckt sind.
123 | passenger.info.reviews.amount.message=\nAnzahl der Bewertungen für einen Fahrgast: %s
124 |
125 | #PROFILE MESSAGES
126 | show.all.user.data.message = Ihre Profildaten:\nName: %s\nTelefonnummer: %s\nTelefonnummer verbergen: %s
127 | edit.user.name.message = Möchten Sie Ihren Namen ändern? Großartig!\nWie möchten Sie genannt werden?
128 | edit.phone.number.message = Kein Problem! Klicken Sie auf den Button, um Ihre Nummer zu teilen, und ich füge sie sofort hinzu \uD83D\uDE09
129 | remove.phone.number.message = Ich sehe, dass Ihre Nummer bereits hinzugefügt wurde \uD83E\uDD29\n\nSie können sie löschen oder einfach aktualisieren, wie Sie möchten \uD83D\uDE09
130 | hidden.phone.number.false.message = Ihre Telefonnummer ist derzeit für den Fahrgast/Fahrer sichtbar, um Sie zu kontaktieren.\n\nWenn Sie die Einstellungen ändern möchten, drücken Sie den "%s" Knopf.
131 | hidden.phone.number.true.message = Ihre Telefonnummer ist derzeit vor den Fahrgästen/Fahrern verborgen, sodass sie diese nicht sehen, wenn sie Ihre Bestellung annehmen.\n\nWenn Sie die Einstellungen ändern möchten, drücken Sie den "%s" Knopf.
132 | successful.data.saved.message = Daten erfolgreich gespeichert \uD83E\uDD73
133 | error.no.phone.number.message = Entschuldigung, aber Sie müssen zuerst eine Telefonnummer hinzufügen \uD83D\uDE14
134 | error.driver.need.exit.settings.menu.message = Leider können Sie keine Bestellungen annehmen, solange Sie sich im Einstellungsmenü befinden \uD83D\uDE14
135 | get.support.message = Sie können uns jederzeit über diesen Kontakt bei Fragen erreichen: @CompaneroSupport
136 |
137 |
138 | #MISC TEXT VALUES
139 | no.value = Nein
140 | yes.value = Ja
141 | empty.value = -
142 | now.value = Jetzt
143 |
--------------------------------------------------------------------------------
/src/main/resources/localization_en_US.properties:
--------------------------------------------------------------------------------
1 | #HOOK MESSAGES
2 | authorize.as.passenger.hook.message = Passenger
3 | authorize.as.driver.hook.message = Driver
4 | confirm.arrival.hook.message = I have arrived
5 | create.new.order.hook.message = Start a driver search
6 | cancel.order.hook.message = Cancel Ride
7 | finish.order.hook.message = Finish Ride
8 | share.location.hook.message = Share Location
9 | update.location.hook.message = Update Location
10 | start.work.shift.hook.message = Start a passenger search
11 | stop.work.shift.hook.message = Stop a passenger search
12 | share.my.contact.hook.message = Share My Contact
13 | skip.share.my.contact.hook.message = Skip Step
14 | add.notes.hook.message = Yes, I have special notes
15 | skip.notes.hook.message = No, I don't
16 | recommended.price.hook.message = %.2f
17 | confirm.order.hook.message = Confirm
18 | free.ride.hook.message = Free Ride
19 | confirm.postponed.order.hook.message = The trip has been agreed
20 | decline.postponed.order.hook.message = The trip has not been agreed
21 |
22 | #USER SETTINGS HOOK MESSAGES
23 | open.settings.hook.message = Settings
24 | get.support.hook.message = Support
25 | exit.settings.hook.message = Exit Settings
26 | back.to.previous.page.hook.message = Back
27 | edit.user.name.hook.message = Change name
28 | edit.phone.number.hook.message = Change phone number
29 | remove.phone.number.hook.message = Remove phone number
30 | edit.share.phone.number.hook.message = Change phone number privacy
31 | reveal.phone.number.hook.message = Reveal phone number
32 | hide.phone.number.hook.message = Hide phone number
33 |
34 |
35 | #INLINE TEXT
36 | write.to.passenger.inline.text = Open chat with passenger
37 | write.to.driver.inline.text = Open chat with driver
38 | accept.inline.text = Accept
39 | open.pickup.point.inline.text = Open PickUp Point on Map
40 | open.destination.point.inline.text = Open Destination Point on Map
41 | add.postponed.departure.details.inline.text = Change departure time
42 | wallet.inline.text=Wallet
43 |
44 |
45 | #MESSAGES
46 | user.policy.agreement.message = NOTE: By using CompaneroBot, you acknowledge that you have read and agreed to this User Policy Agreement and Privacy Policy.
47 | request.contacts.message = Now, let's get to know each other!\n\nIf you prefer, you can share your phone number or skip this step.\n\nNone of this options won't affect your experience\uD83D\uDE09
48 | message.after.registration.with.phone.number = %s... Writing down... You have a beautiful name! Nice to meet you!
49 | message.after.registration.without.phone.number = No problem! You can add it yourself at any time.
50 | message.missing.user.tag.general=A little more attention: \nWe respect your privacy, but we have to inform you that due to the lack of a username (the one starting with "@") in your Telegram profile and the absence of a phone number, the driver or passenger will not be able to contact you directly if necessary.\n\nWe do not ask you to add any of this, we just warn you\uD83D\uDE09
51 | missing.user.tag.without.number.passenger.warn.message=A little more attention: \nWe respect your privacy, but we have to inform you that due to the lack of a username (the one starting with "@") in your Telegram profile and the absence of a phone number, the driver will not be able to contact you directly if necessary.\n\nWe do not ask you to add any of this, we just warn you\uD83D\uDE09
52 | missing.user.tag.without.number.driver.warn.message=A little more attention: \nWe respect your privacy, but we have to inform you that due to the lack of a username (the one starting with "@") in your Telegram profile and the absence of a phone number, the passenger will not be able to contact you directly if necessary.\n\nWe do not ask you to add any of this, we just warn you\uD83D\uDE09
53 | incorrect.contact.message = It looks like the contact received does not relate to you.
54 | choose.role.message = Now, let's choose your role! Whom do you wanna be?
55 | phone.number.message=\nPhone number: +%s
56 | rating.message=\nRating: %s/10
57 | financial.operations.warn.message=\n\nATTENTION: We do not interfere in any way with financial transactions between the driver and the passenger, the issue of payment and its method is decided by the parties independently!
58 | departure.time.order.message=\nDeparture time: %s
59 | order.price.message=\nPrice: %.2f %s
60 | order.free.ride.message=\nThis trip is FREE OF CHARGE
61 | further.contacts.postponed.message=\n\nAll you have to do is agree on all the details directly.
62 | after.rate.message=Thank you for your feedback! \u2764\uFE0F
63 | restricted.location.message=It looks like that we don't work in this region. Please, choose another one.
64 | restricted.phone.number.message=It looks like you have a phone number from a restricted region.\n\nPlease, register with another phone number to have full access to the features.
65 |
66 | #PASSENGER MESSAGES
67 | passenger.role.welcome.message = Okie-Dokie!\n\nIf you would like to have a ride, please press the "%s" button.
68 | request.pickup.point.passenger.message=Sure! Where are you located?\n\nHow to send location: \uD83D\uDCCE (Attachment icon) -> "Location" -> Choose pickup point on map
69 | request.destination.point.passenger.message=Now where do you wanna go?\n\nHow to send location: \uD83D\uDCCE (Attachment icon) -> "Location" -> Choose destination point on map
70 | ask.if.notes.needed.message = Done. Do you have any notes for driver?
71 | add.notes.message = Sure. What can a driver do for you?
72 | add.price.order.message=According to our calculations, the recommended cost of the trip is %.2f %s.\nYou can specify your own price in local currency by writing it directly in the chat (for example, "5" or "5.50").\n\nBut if you can't afford to pay, click the "Free ride" button ;)
73 | price.error.more.than.int.max.message=Unfortunately, you have specified more than the maximum allowable cost of one trip.
74 | price.error.less.than.0.message = Sorry, but you can't specify a negative amount :)
75 | price.error.other.message = Oops... Something went wrong. Send me the price in the format as shown in the example: "5" or "5.50"
76 | confirmation.reminder.message = If everything is correct, you can confirm it ;)
77 | confirm.order.by.passenger.message = The ride request is created and sent to other drivers!\n\nWhen driver will be found - I'll let you know ;)
78 | further.steps.for.passenger.postponed.message = When you agree with the driver, press the "%s" button, or press "%s" if you need another one.
79 | cancel.trip.by.passenger.self.message = Your trip is canceled!\n\nIf you would like to have a new ride, please press the "%s" button
80 | driver.arrived.passenger.message = Your driver has arrived and is waiting for you!
81 | finished.order.passenger.message=Your trip is finished!\n\nIf you would like to have a new ride, please press the "%s" button
82 | cancel.trip.by.driver.message = Your trip is canceled by driver! Sorry about that!\n\nBut we've already sent your ride request to other drivers ;)
83 | declined.postponed.trip.for.passenger.message = What a pity that you couldn't arrange a ride with a driver :c\n\nBut we've already sent your ride request to other drivers ;)
84 | confirmed.postponed.trip.for.passenger.message = You agreed your trip, cool! Now you can communicate with the driver directly about any further steps.\n\nIf you would like to have a new ride, please press the "%s" button
85 | add.review.on.driver.for.passengers.message=Order ID: %s\nPlease, tell us how did your trip with the driver go?
86 | confirmation.passenger.order.base.message=Please check your trip details:\nPickup point: %s\nDestination point: %s\nNotes: %s
87 | driver.info.base.message=I found the best driver for you!\n\nName: %s
88 | driver.info.car.plate.message=\nCar: %s, %s, %s
89 | driver.info.car.plate.postponed.message=\nCar: %s
90 | driver.info.reviews.amount.message=\nNumber of reviews for a driver: %s
91 | driver.info.missing.contacts.message=\n\nUnfortunately, the driver decided not to provide his contact information. But he will be able to contact you if your contact information is not hidden.
92 | driver.info.location.message=\n\nDriver will share his location with you in a while!
93 | payment.reminder.message=Please, do not forget to pay for the ride after it ends.\nTo pay: %.2f %s.\n\nIf you wish, you can use the crypto wallet in Telegram to transfer funds to the driver.
94 |
95 | #DRIVER MESSAGES
96 | request.driver.location.message = Please, share your location with a passenger using a "%s" button!
97 | unavailable.order.message = Unfortunately, this ride request is no longer available. Please, choose another one.
98 | has.already.order.error.message = We're sorry, but it looks like you already have unfinished rides. Please, accept new rides only after you have finished yours.
99 | order.id.part.message = Order ID:
100 | car.model.request.message = Wanna become a driver? Cool! Tell me about you car please, what model you got?
101 | driver.location.message = Your driver is located in %s km(s) from your pickup point :)\n\nApproximately arriving time: %d min(s)
102 | further.steps.for.driver.postponed.message = When you agree the trip with the passenger, press the "%s" button, or press "%s" if this order does not suit you.
103 | future.arrival.reminder.message = When you'll be on pickup point, please, press the "%s" button!
104 | cancel.trip.by.passenger.message = Your trip is canceled by passenger! Sorry about that!\n\nNow you will start getting new offers :)
105 | stop.shift.message = If you want to stop searching for a passenger, press the "%s" button
106 | start.shift.message = If you want to start searching for a passenger, press the "%s" button
107 | car.color.request.message = Nice car! What color is it?
108 | car.plate.number.request.message = Great color! What's the plate number you have on it?
109 | driver.location.request.message=The last thing, please send me a point on the map where you would like to receive passenger requests.\n\nYou will receive trip requests in an area 25km from you for immediate trips and 125km from you for trips that will be requested in advance.\n\nJust press the "%s" button or send the location you need. In any case, you can update it later if needed ;)
110 | car.info.registration.finished.message=Ok, we're done with registration! Congrats!\n\nNow, here you will receive new ride requests from passengers.
111 | destination.point.driver.message = The passenger is notified that you have arrived!\n\nYour destination point: %s\n\nYou can open it on a map using the button below ;)
112 | future.finish.order.reminder.message = When you will be on destination point, please press the "%s" button :)
113 | finished.order.driver.message = Your trip is finished!\n\nNow you will start getting new offers :)
114 | cancel.trip.by.driver.self.message = Your trip is canceled!\n\nNow you will start getting new offers :)
115 | declined.postponed.trip.for.driver.message = What a pity that you couldn't arrange a ride with a passenger :c\n\nBut don't worry, you'll be getting new offers soon!
116 | confirmed.postponed.trip.for.driver.message = You agreed your trip, cool! Now you can communicate with the passenger directly about any further steps.\n\nAnd now you will receive new offers!
117 | departure.details.message = If you need a car for a specific date and time, please specify these details here \uD83D\uDE4F
118 | add.review.on.passenger.for.drivers.message=Order ID: %s\nPlease, tell us how did your trip with the passenger go?
119 | new.order.base.message=Order ID: %s\nPickup: %s\nApproximate destination point: %s\nTrip Length: %s Km\nNotes: %s
120 | location.sent.to.passenger.message=Your location is sent to passenger, thanks!
121 | passenger.info.base.message=Here's some information about your passenger:\n\nName: %s
122 | passenger.info.missing.contacts.message=\n\nUnfortunately, the passenger decided not to provide his contact information. But he will be able to contact you if your contact information is not hidden.
123 | passenger.info.reviews.amount.message=\nNumber of reviews for a passenger: %s
124 |
125 | #PROFILE MESSAGES
126 | show.all.user.data.message = Your profile data:\nName: %s\nPhone number: %s\nHide phone number: %s
127 | edit.user.name.message = Want to change your name? Great!\nHow do you want to be called?
128 | edit.phone.number.message = No problem! Click the button to share your number and I'll add it instantly\uD83D\uDE09
129 | remove.phone.number.message = I see that your number has already been added \uD83E\uDD29\n\nYou can delete it or just update it, as you prefer \uD83D\uDE09
130 | hidden.phone.number.false.message = Your phone number is currently available for the passenger/driver to contact you.\n\nIf you want to change the settings, press the "%s" button.
131 | hidden.phone.number.true.message = Your phone number is currently hidden from the passengers/drivers, so they won't see it if they take your order.\n\nIf you want to change the settings, press the "%s" button.
132 | successful.data.saved.message = Data successfully saved \uD83E\uDD73
133 | error.no.phone.number.message = Sorry, but you need to add a phone number first \uD83D\uDE14
134 | error.driver.need.exit.settings.menu.message = Unfortunately, you cannot accept orders while you are in the settings menu \uD83D\uDE14
135 | get.support.message = You can always reach us at this contact with any question: @CompaneroSupport
136 |
137 |
138 | #MISC TEXT VALUES
139 | no.value = No
140 | yes.value = Yes
141 | empty.value = -
142 | now.value = Now
--------------------------------------------------------------------------------
/src/main/resources/localization_es_ES.properties:
--------------------------------------------------------------------------------
1 | #HOOK MESSAGES
2 | authorize.as.passenger.hook.message = Pasajero
3 | authorize.as.driver.hook.message = Conductor
4 | confirm.arrival.hook.message = He llegado
5 | create.new.order.hook.message = Iniciar búsqueda de conductor
6 | cancel.order.hook.message = Cancelar viaje
7 | finish.order.hook.message = Finalizar viaje
8 | share.location.hook.message = Compartir ubicación
9 | update.location.hook.message = Actualizar ubicación
10 | start.work.shift.hook.message = Iniciar búsqueda de pasajeros
11 | stop.work.shift.hook.message = Detener búsqueda de pasajeros
12 | share.my.contact.hook.message = Compartir mi contacto
13 | skip.share.my.contact.hook.message = Saltar paso
14 | add.notes.hook.message = Sí, tengo notas especiales
15 | skip.notes.hook.message = No, no tengo
16 | recommended.price.hook.message = %.2f
17 | confirm.order.hook.message = Confirmar
18 | free.ride.hook.message = Viaje gratis
19 | confirm.postponed.order.hook.message = El viaje ha sido acordado
20 | decline.postponed.order.hook.message = El viaje no ha sido acordado
21 |
22 | #USER SETTINGS HOOK MESSAGES
23 | open.settings.hook.message = Ajustes
24 | get.support.hook.message = Soporte
25 | exit.settings.hook.message = Salir de ajustes
26 | back.to.previous.page.hook.message = Atrás
27 | edit.user.name.hook.message = Cambiar nombre
28 | edit.phone.number.hook.message = Cambiar número de teléfono
29 | remove.phone.number.hook.message = Eliminar número de teléfono
30 | edit.share.phone.number.hook.message = Cambiar privacidad del número de teléfono
31 | reveal.phone.number.hook.message = Mostrar número de teléfono
32 | hide.phone.number.hook.message = Ocultar número de teléfono
33 |
34 |
35 | #INLINE TEXT
36 | write.to.passenger.inline.text = Abrir chat con pasajero
37 | write.to.driver.inline.text = Abrir chat con conductor
38 | accept.inline.text = Aceptar
39 | open.pickup.point.inline.text = Abrir punto de recogida en el mapa
40 | open.destination.point.inline.text = Abrir punto de destino en el mapa
41 | add.postponed.departure.details.inline.text = Cambiar hora de salida
42 | wallet.inline.text=Cartera
43 |
44 |
45 | #MESSAGES
46 | user.policy.agreement.message = NOTA: Al usar CompaneroBot, reconoces que has leído y aceptado este Acuerdo de Política de Usuario y la Política de Privacidad.
47 | request.contacts.message = Ahora, ¡vamos a conocernos!\n\nSi prefieres, puedes compartir tu número de teléfono o saltar este paso.\n\nNinguna de estas opciones afectará tu experiencia\uD83D\uDE09
48 | message.after.registration.with.phone.number = %s... Anotando... ¡Tienes un nombre hermoso! ¡Encantado de conocerte!
49 | message.after.registration.without.phone.number = ¡No hay problema! Puedes añadirlo tú mismo en cualquier momento.
50 | message.missing.user.tag.general=Un poco más de atención: \nRespetamos tu privacidad, pero tenemos que informarte que debido a la falta de un nombre de usuario (el que comienza con "@") en tu perfil de Telegram y la ausencia de un número de teléfono, el conductor o pasajero no podrá contactarte directamente si es necesario.\n\nNo te pedimos que añadas ninguno de esto, solo te advertimos\uD83D\uDE09
51 | missing.user.tag.without.number.passenger.warn.message=Un poco más de atención: \nRespetamos tu privacidad, pero tenemos que informarte que debido a la falta de un nombre de usuario (el que comienza con "@") en tu perfil de Telegram y la ausencia de un número de teléfono, el conductor no podrá contactarte directamente si es necesario.\n\nNo te pedimos que añadas ninguno de esto, solo te advertimos\uD83D\uDE09
52 | missing.user.tag.without.number.driver.warn.message=Un poco más de atención: \nRespetamos tu privacidad, pero tenemos que informarte que debido a la falta de un nombre de usuario (el que comienza con "@") en tu perfil de Telegram y la ausencia de un número de teléfono, el pasajero no podrá contactarte directamente si es necesario.\n\nNo te pedimos que añadas ninguno de esto, solo te advertimos\uD83D\uDE09
53 | incorrect.contact.message = Parece que el contacto recibido no te pertenece.
54 | choose.role.message = Ahora, ¡vamos a elegir tu rol! ¿Quién quieres ser?
55 | phone.number.message=\nNúmero de teléfono: +%s
56 | rating.message=\nCalificación: %s/10
57 | financial.operations.warn.message=\n\nATENCIÓN: No intervenimos de ninguna manera en las transacciones financieras entre el conductor y el pasajero; el asunto del pago y su método son decididos por las partes de manera independiente.
58 | departure.time.order.message=\nHora de salida: %s
59 | order.price.message=\nPrecio: %.2f %s
60 | order.free.ride.message=\nEste viaje es GRATUITO
61 | further.contacts.postponed.message=\n\nSolo tienes que acordar todos los detalles directamente.
62 | after.rate.message=¡Gracias por tu opinión! \u2764\uFE0F
63 | restricted.location.message=Parece que no trabajamos en esta región. Por favor, elige otra.
64 | restricted.phone.number.message=Parece que tienes un número de teléfono de una región restringida.\n\nPor favor, regístrate con otro número de teléfono para tener acceso completo a las funciones.
65 |
66 | #PASSENGER MESSAGES
67 | passenger.role.welcome.message = ¡Vale!\n\nSi quieres realizar un viaje, por favor presiona el botón "%s".
68 | request.pickup.point.passenger.message=¡Claro! ¿Dónde te encuentras?\n\nCómo enviar ubicación: \uD83D\uDCCE (Icono adjunto) -> "Ubicación" -> Escoger punto de recogida en el mapa
69 | request.destination.point.passenger.message=Ahora, ¿a dónde quieres ir?\n\nCómo enviar ubicación: \uD83D\uDCCE (Icono adjunto) -> "Ubicación" -> Escoger punto de destino en el mapa
70 | ask.if.notes.needed.message = Listo. ¿Tienes alguna nota para el conductor?
71 | add.notes.message = Claro. ¿Qué puede hacer el conductor por ti?
72 | add.price.order.message = Según nuestros cálculos, el costo recomendado del viaje es %.2f %s.\nPuedes especificar tu propio precio en la moneda local escribiéndolo directamente en el chat (por ejemplo, "5" o "5.50").\n\nPero si no puedes pagar, haz clic en el botón "Viaje gratis" ;)
73 | price.error.more.than.int.max.message = Desafortunadamente, has especificado más que el costo máximo permitido para un viaje.
74 | price.error.less.than.0.message = Lo siento, pero no puedes especificar una cantidad negativa :)
75 | price.error.other.message = Ups... Algo salió mal. Envíame el precio en el formato mostrado en el ejemplo: "5" o "5.50"
76 | confirmation.reminder.message = Si todo está correcto, puedes confirmarlo ;)
77 | confirm.order.by.passenger.message = ¡La solicitud de viaje ha sido creada y enviada a otros conductores!\n\nCuando se encuentre un conductor, te lo haré saber ;)
78 | further.steps.for.passenger.postponed.message = Cuando llegues a un acuerdo con el conductor, presiona el botón "%s", o presiona "%s" si necesitas otro.
79 | cancel.trip.by.passenger.self.message = ¡Tu viaje ha sido cancelado!\n\nSi deseas tener un nuevo viaje, por favor presiona el botón "%s".
80 | driver.arrived.passenger.message = ¡Tu conductor ha llegado y te está esperando!
81 | finished.order.passenger.message = ¡Tu viaje ha terminado!\n\nSi deseas tener un nuevo viaje, por favor presiona el botón "%s".
82 | cancel.trip.by.driver.message = ¡Tu viaje ha sido cancelado por el conductor! Lo siento por eso!\n\nPero ya hemos enviado tu solicitud de viaje a otros conductores ;)
83 | declined.postponed.trip.for.passenger.message = Qué pena que no pudiste organizar un viaje con un conductor :c\n\nPero ya hemos enviado tu solicitud de viaje a otros conductores ;)
84 | confirmed.postponed.trip.for.passenger.message = Has acordado tu viaje, ¡genial! Ahora puedes comunicarte directamente con el conductor sobre cualquier paso adicional.\n\nSi deseas tener un nuevo viaje, por favor presiona el botón "%s"
85 | add.review.on.driver.for.passengers.message=ID de orden: %s\nPor favor, cuéntenos, ¿cómo fue su viaje con el conductor?
86 | confirmation.passenger.order.base.message=Por favor, verifica los detalles de tu viaje:\nPunto de recogida: %s\nDestino: %s\nNotas: %s
87 | driver.info.base.message=¡He encontrado al mejor conductor para ti!\n\nNombre: %s
88 | driver.info.car.plate.message=\nAuto: %s, %s, %s
89 | driver.info.car.plate.postponed.message=\nAuto: %s
90 | driver.info.reviews.amount.message=\nNúmero de reseñas para un conductor: %s
91 | driver.info.missing.contacts.message=\n\nLamentablemente, el conductor decidió no proporcionar su información de contacto. Pero podrá contactarte si tu información de contacto no está oculta.
92 | driver.info.location.message=\n\n¡El conductor compartirá su ubicación contigo en breve!
93 | payment.reminder.message=Por favor, no olvides pagar el viaje después de que termine.\nA pagar: %.2f %s.\n\nSi lo deseas, puedes usar la billetera criptográfica en Telegram para transferir fondos al conductor.
94 |
95 | #DRIVER MESSAGES
96 | request.driver.location.message = Por favor, comparte tu ubicación con un pasajero usando el botón "%s".
97 | unavailable.order.message = Desafortunadamente, esta solicitud de viaje ya no está disponible. Por favor, elige otra.
98 | has.already.order.error.message = Lo sentimos, pero parece que ya tienes viajes sin finalizar. Por favor, acepta nuevos viajes solo después de haber terminado los tuyos.
99 | order.id.part.message = ID de orden:
100 | car.model.request.message = ¿Quieres ser conductor? ¡Genial! Dime, por favor, ¿qué modelo es tu coche?
101 | driver.location.message = Tu conductor está ubicado a %s km(s) de tu punto de recogida :)\n\nTiempo aproximado de llegada: %d min(s)
102 | further.steps.for.driver.postponed.message = Cuando llegues a un acuerdo con el pasajero, presiona el botón "%s", o presiona "%s" si este pedido no te conviene.
103 | future.arrival.reminder.message = Cuando estés en el punto de recogida, por favor, presiona el botón "%s".
104 | cancel.trip.by.passenger.message = ¡Tu viaje ha sido cancelado por el pasajero! Lo siento por eso!\n\nAhora empezarás a recibir nuevas ofertas :)
105 | stop.shift.message = Si quieres dejar de buscar pasajeros, presiona el botón "%s".
106 | start.shift.message = Si quieres empezar a buscar pasajeros, presiona el botón "%s".
107 | car.color.request.message = ¡Bonito coche! ¿De qué color es?
108 | car.plate.number.request.message = ¡Gran color! ¿Cuál es el número de placa que tiene?
109 | driver.location.request.message=Lo último, por favor envíame un punto en el mapa donde te gustaría recibir solicitudes de pasajeros.\n\nRecibirás solicitudes de viaje en un área de 25 km desde tu ubicación para viajes inmediatos y de 125 km para viajes que se soliciten con antelación.\n\nSolo presiona el botón "%s" o envía la ubicación que necesitas. En cualquier caso, luego podrás actualizarla si es necesario ;)
110 | car.info.registration.finished.message=Ok, hemos terminado con el registro! ¡Felicidades!\n\nAhora, aquí recibirás nuevas solicitudes de viaje de los pasajeros.
111 | destination.point.driver.message = ¡El pasajero ha sido notificado de que has llegado!\n\nTu punto de destino: %s\n\nPuedes abrirlo en el mapa usando el botón de abajo ;)
112 | future.finish.order.reminder.message = Cuando estés en el punto de destino, por favor presiona el botón "%s".
113 | finished.order.driver.message = ¡Tu viaje ha terminado!\n\nAhora empezarás a recibir nuevas ofertas :)
114 | cancel.trip.by.driver.self.message = ¡Tu viaje ha sido cancelado!\n\nAhora empezarás a recibir nuevas ofertas :)
115 | declined.postponed.trip.for.driver.message = Qué pena que no pudiste organizar un viaje con un pasajero :c\n\nPero no te preocupes, pronto recibirás nuevas ofertas!
116 | confirmed.postponed.trip.for.driver.message = Has acordado tu viaje, ¡genial! Ahora puedes comunicarte directamente con el pasajero sobre cualquier paso adicional.\n\n¡Y ahora recibirás nuevas ofertas!
117 | departure.details.message = Si necesitas un coche para una fecha y hora específicas, por favor especifica estos detalles aquí \uD83D\uDE4F
118 | add.review.on.passenger.for.drivers.message=ID de orden: %s\nPor favor, cuéntenos, ¿cómo fue su viaje con el pasajero?
119 | new.order.base.message=ID de orden: %s\nRecogida: %s\nPunto de destino aproximado: %s\nLongitud del viaje: %s Km\nNotas: %s
120 | location.sent.to.passenger.message=Tu ubicación ha sido enviada al pasajero, ¡gracias!
121 | passenger.info.base.message=Aquí tienes alguna información sobre tu pasajero:\n\nNombre: %s
122 | passenger.info.missing.contacts.message=\n\nLamentablemente, el pasajero decidió no proporcionar su información de contacto. Pero podrá contactarte si tu información de contacto no está oculta.
123 | passenger.info.reviews.amount.message=\nNúmero de reseñas para un pasajero: %s
124 |
125 | #PROFILE MESSAGES
126 | show.all.user.data.message = Los datos de tu perfil:\nNombre: %s\nNúmero de teléfono: %s\nOcultar número de teléfono: %s
127 | edit.user.name.message = ¿Quieres cambiar tu nombre? ¡Genial!\n¿Cómo te gustaría que te llamen?
128 | edit.phone.number.message = ¡Sin problema! Haz clic en el botón para compartir tu número y lo añadiré al instante\uD83D\uDE09
129 | remove.phone.number.message = Veo que tu número ya ha sido añadido \uD83E\uDD29\n\nPuedes eliminarlo o simplemente actualizarlo, como prefieras \uD83D\uDE09
130 | hidden.phone.number.false.message = Tu número de teléfono está actualmente disponible para que el pasajero/conductor te contacte.\n\nSi quieres cambiar la configuración, presiona el botón "%s".
131 | hidden.phone.number.true.message = Tu número de teléfono está actualmente oculto para los pasajeros/conductores, así que no lo verán si toman tu pedido.\n\nSi quieres cambiar la configuración, presiona el botón "%s".
132 | successful.data.saved.message = Datos guardados exitosamente \uD83E\uDD73
133 | error.no.phone.number.message = Lo siento, pero necesitas añadir un número de teléfono primero \uD83D\uDE14
134 | error.driver.need.exit.settings.menu.message = Desafortunadamente, no puedes aceptar pedidos mientras estás en el menú de configuración \uD83D\uDE14
135 | get.support.message = Siempre puedes contactarnos en este contacto con cualquier pregunta: @CompaneroSupport
136 |
137 |
138 | #MISC TEXT VALUES
139 | no.value = No
140 | yes.value = Sí
141 | empty.value = -
142 | now.value = Ahora
--------------------------------------------------------------------------------
/src/main/resources/localization_pt_PT.properties:
--------------------------------------------------------------------------------
1 | #HOOK MESSAGES
2 | authorize.as.passenger.hook.message = Passageiro
3 | authorize.as.driver.hook.message = Condutor
4 | confirm.arrival.hook.message = Já cheguei
5 | create.new.order.hook.message = Iniciar uma pesquisa de condutor
6 | cancel.order.hook.message = Cancelar Viagem
7 | finish.order.hook.message = Terminar Viagem
8 | share.location.hook.message = Partilhar Localização
9 | update.location.hook.message = Atualizar Localização
10 | start.work.shift.hook.message = Iniciar uma pesquisa de passageiros
11 | stop.work.shift.hook.message = Parar uma pesquisa de passageiros
12 | share.my.contact.hook.message = Partilhar o Meu Contacto
13 | skip.share.my.contact.hook.message = Saltar Passo
14 | add.notes.hook.message = Sim, tenho notas especiais
15 | skip.notes.hook.message = Não, não tenho
16 | recommended.price.hook.message = %.2f
17 | confirm.order.hook.message = Confirmar
18 | free.ride.hook.message = Viagem Gratuita
19 | confirm.postponed.order.hook.message = A viagem foi acordada
20 | decline.postponed.order.hook.message = A viagem não foi acordada
21 |
22 | #USER SETTINGS HOOK MESSAGES
23 | open.settings.hook.message = Definições
24 | get.support.hook.message = Apoio
25 | exit.settings.hook.message = Sair das Definições
26 | back.to.previous.page.hook.message = Voltar
27 | edit.user.name.hook.message = Alterar nome
28 | edit.phone.number.hook.message = Alterar número de telefone
29 | remove.phone.number.hook.message = Remover número de telefone
30 | edit.share.phone.number.hook.message = Alterar privacidade do número de telefone
31 | reveal.phone.number.hook.message = Revelar número de telefone
32 | hide.phone.number.hook.message = Ocultar número de telefone
33 |
34 |
35 | #INLINE TEXT
36 | write.to.passenger.inline.text = Abrir chat com passageiro
37 | write.to.driver.inline.text = Abrir chat com condutor
38 | accept.inline.text = Aceitar
39 | open.pickup.point.inline.text = Abrir Ponto de Recolha no Mapa
40 | open.destination.point.inline.text = Abrir Ponto de Destino no Mapa
41 | add.postponed.departure.details.inline.text = Alterar hora de partida
42 | wallet.inline.text=Carteira
43 |
44 |
45 | #MESSAGES
46 | user.policy.agreement.message = NOTA: Ao usar o CompaneroBot, você reconhece que leu e aceitou este Acordo de Política de Usuário e a Política de Privacidade.
47 | request.contacts.message = Agora, vamos conhecer-nos melhor!\n\nSe preferir, pode partilhar o seu número de telefone ou saltar este passo.\n\nNenhuma destas opções afetará a sua experiência😉
48 | message.after.registration.with.phone.number = %s... A escrever... Tens um nome bonito! Prazer em conhecer-te!
49 | message.after.registration.without.phone.number = Sem problema! Pode adicioná-lo a qualquer momento.
50 | message.missing.user.tag.general=Um pouco mais de atenção:\nRespeitamos a sua privacidade, mas temos de informar que devido à falta de um nome de utilizador (aquele que começa com "@") no seu perfil do Telegram e à ausência de um número de telefone, o condutor ou passageiro não conseguirá contactá-lo diretamente se necessário.\n\nNão pedimos que adicione nenhum destes, apenas o avisamos😉
51 | missing.user.tag.without.number.passenger.warn.message=Um pouco mais de atenção:\nRespeitamos a sua privacidade, mas temos de informar que devido à falta de um nome de utilizador (aquele que começa com "@") no seu perfil do Telegram e à ausência de um número de telefone, o condutor não conseguirá contactá-lo diretamente se necessário.\n\nNão pedimos que adicione nenhum destes, apenas o avisamos😉
52 | missing.user.tag.without.number.driver.warn.message=Um pouco mais de atenção:\nRespeitamos a sua privacidade, mas temos de informar que devido à falta de um nome de utilizador (aquele que começa com "@") no seu perfil do Telegram e à ausência de um número de telefone, o passageiro não conseguirá contactá-lo diretamente se necessário.\n\nNão pedimos que adicione nenhum destes, apenas o avisamos😉
53 | incorrect.contact.message = Parece que o contacto recebido não se relaciona consigo.
54 | choose.role.message = Agora, vamos escolher o seu papel! Quem gostaria de ser?
55 | phone.number.message=\nNúmero de telefone: +%s
56 | rating.message=\nAvaliação: %s/10
57 | financial.operations.warn.message=\n\nATENÇÃO: Não interferimos de forma alguma nas transações financeiras entre o motorista e o passageiro; a questão do pagamento e seu método são decididos pelas partes de forma independente.
58 | departure.time.order.message=\nHora de partida: %s
59 | order.price.message=\nPreço: %.2f %s
60 | order.free.ride.message=\nEsta viagem é GRATUITA
61 | further.contacts.postponed.message=\n\nVocê só precisa concordar com todos os detalhes diretamente.
62 | after.rate.message=Obrigado por sua opinião! \u2764\uFE0F
63 | restricted.location.message=Parece que não atuamos nesta região. Por favor, escolha outra.
64 | restricted.phone.number.message=Parece que você tem um número de telefone de uma região restrita.\n\nPor favor, registre-se com outro número de telefone para ter acesso completo aos recursos.
65 |
66 | #PASSENGER MESSAGES
67 | passenger.role.welcome.message = Okay!\n\nSe quiseres uma boleia, por favor pressiona o botão "%s".
68 | request.pickup.point.passenger.message=Claro! Onde estás?\n\nComo enviar a localização: \uD83D\uDCCE (ícone de anexo) -> "Localização" -> Escolhe o ponto de partida no mapa
69 | request.destination.point.passenger.message=E agora, para onde queres ir?\n\nComo enviar a localização: \uD83D\uDCCE (ícone de anexo) -> "Localização" -> Escolhe o ponto de destino no mapa
70 | ask.if.notes.needed.message = Pronto. Tens alguma nota para o motorista?
71 | add.notes.message = Claro. O que pode o motorista fazer por ti?
72 | add.price.order.message=De acordo com os nossos cálculos, o custo recomendado da viagem é %.2f %s.\nPodes especificar o teu próprio preço em moeda local escrevendo diretamente no chat (por exemplo, "5" ou "5.50").\n\nMas se não puderes pagar, clica no botão "Viagem grátis" ;)
73 | price.error.more.than.int.max.message=Infelizmente, especificaste um valor superior ao custo máximo permitido por viagem.
74 | price.error.less.than.0.message = Desculpa, mas não podes especificar um valor negativo :)
75 | price.error.other.message = Ups... Algo correu mal. Envia-me o preço no formato mostrado no exemplo: "5" ou "5.50"
76 | confirmation.reminder.message = Se tudo estiver correto, podes confirmar ;)
77 | confirm.order.by.passenger.message = O pedido de viagem foi criado e enviado a outros motoristas!\n\nQuando um motorista for encontrado, eu avisarei ;)
78 | further.steps.for.passenger.postponed.message = Quando acordares com o motorista, pressiona o botão "%s", ou pressiona "%s" se precisares de outro.
79 | cancel.trip.by.passenger.self.message = A tua viagem foi cancelada!\n\nSe quiseres uma nova viagem, por favor pressiona o botão "%s"
80 | driver.arrived.passenger.message = O teu motorista chegou e está à tua espera!
81 | finished.order.passenger.message = A tua viagem terminou!\n\nSe quiseres uma nova viagem, por favor pressiona o botão "%s"
82 | cancel.trip.by.driver.message = A tua viagem foi cancelada pelo motorista! Lamentamos o sucedido!\n\nMas já enviamos o teu pedido de viagem a outros motoristas ;)
83 | declined.postponed.trip.for.passenger.message = Que pena que não conseguiste organizar uma viagem com o motorista :c\n\nMas já enviamos o teu pedido de viagem a outros motoristas ;)
84 | confirmed.postponed.trip.for.passenger.message = Acordaste a tua viagem, que bom! Agora podes comunicar diretamente com o motorista sobre os próximos passos.\n\nSe quiseres uma nova viagem, por favor pressiona o botão "%s"
85 | add.review.on.driver.for.passengers.message=ID do Pedido: %s\nDiga-nos, por favor, como correu a sua viagem com o motorista?
86 | confirmation.passenger.order.base.message=Por favor, verifique os detalhes da sua viagem:\nPonto de embarque: %s\nDestino: %s\nNotas: %s
87 | driver.info.base.message=Encontrei o melhor motorista para você!\n\nNome: %s
88 | driver.info.car.plate.message=\nCarro: %s, %s, %s
89 | driver.info.car.plate.postponed.message=\nCarro: %s
90 | driver.info.reviews.amount.message=\nNúmero de avaliações para um motorista: %s
91 | driver.info.missing.contacts.message=\n\nInfelizmente, o motorista decidiu não fornecer suas informações de contato. Mas ele poderá contatá-lo se suas informações de contato não estiverem ocultas.
92 | driver.info.location.message=\n\nO motorista compartilhará sua localização com você em breve!
93 | payment.reminder.message=Por favor, não se esqueça de pagar a viagem após o seu término.\nA pagar: %.2f %s.\n\nSe desejar, você pode usar a carteira de criptomoedas no Telegram para transferir fundos ao motorista.
94 |
95 | #DRIVER MESSAGES
96 | request.driver.location.message = Por favor, partilhe a sua localização com um passageiro usando o botão "%s"!
97 | unavailable.order.message = Infelizmente, este pedido de viagem já não está disponível. Por favor, escolha outro.
98 | has.already.order.error.message = Lamentamos, mas parece que já tem viagens inacabadas. Por favor, aceite novas viagens apenas após terminar as suas.
99 | order.id.part.message = ID do Pedido:
100 | car.model.request.message = Quer tornar-se motorista? Ótimo! Diga-me por favor, qual é o modelo do seu carro?
101 | driver.location.message = O seu motorista está a %s km(s) do seu ponto de recolha :)\n\nTempo aproximado de chegada: %d min(s)
102 | further.steps.for.driver.postponed.message = Quando concordar com a viagem com o passageiro, pressione o botão "%s", ou pressione "%s" se este pedido não for adequado para si.
103 | future.arrival.reminder.message = Quando estiver no ponto de recolha, por favor, pressione o botão "%s"!
104 | cancel.trip.by.passenger.message = A sua viagem foi cancelada pelo passageiro! Lamentamos por isso!\n\nAgora começará a receber novas ofertas :)
105 | stop.shift.message = Se quiser parar de procurar por um passageiro, pressione o botão "%s"
106 | start.shift.message = Se quiser começar a procurar por um passageiro, pressione o botão "%s"
107 | car.color.request.message = Que bela cor de carro! Qual é?
108 | car.plate.number.request.message = Que cor fantástica! Qual é o número da matrícula do seu carro?
109 | driver.location.request.message=Por último, por favor envie-me um ponto no mapa onde gostaria de receber pedidos de passageiros.\n\nReceberá pedidos de viagem numa área de 25km de si para viagens imediatas e 125km para viagens que serão solicitadas com antecedência.\n\nBasta pressionar o botão "%s" ou enviar a localização que precisas. De qualquer forma, podes atualizá-la depois, se necessário ;)
110 | car.info.registration.finished.message=Ok, terminamos o registo! Parabéns!\n\nAgora, aqui você receberá novos pedidos de viagem dos passageiros.
111 | destination.point.driver.message = O passageiro foi notificado de que chegou!\n\nO seu ponto de destino: %s\n\nPode abri-lo no mapa usando o botão abaixo ;)
112 | future.finish.order.reminder.message = Quando estiver no ponto de destino, por favor pressione o botão "%s" :)
113 | finished.order.driver.message = A sua viagem terminou!\n\nAgora começará a receber novas ofertas :)
114 | cancel.trip.by.driver.self.message = A sua viagem foi cancelada!\n\nAgora começará a receber novas ofertas :)
115 | declined.postponed.trip.for.driver.message = Que pena que não conseguiu organizar uma viagem com o passageiro :c\n\nMas não se preocupe, em breve receberá novas ofertas!
116 | confirmed.postponed.trip.for.driver.message = Concordou com a sua viagem, ótimo! Agora pode comunicar diretamente com o passageiro sobre quaisquer passos adicionais.\n\nE agora receberá novas ofertas!
117 | departure.details.message = Se precisar de um carro para uma data e hora específicas, por favor especifique esses detalhes aqui \uD83D\uDE4F
118 | add.review.on.passenger.for.drivers.message=ID do Pedido: %s\nPor favor, diga-nos, como correu a sua viagem com o passageiro?
119 | new.order.base.message=ID do Pedido: %s\nPonto de embarque: %s\nPonto de destino aproximado: %s\nComprimento da viagem: %s Km\nNotas: %s
120 | location.sent.to.passenger.message=Sua localização foi enviada ao passageiro, obrigado!
121 | passenger.info.base.message=Aqui estão algumas informações sobre seu passageiro:\n\nNome: %s
122 | passenger.info.missing.contacts.message=\n\nInfelizmente, o passageiro decidiu não fornecer suas informações de contato. Mas ele poderá contatá-lo se suas informações de contato não estiverem ocultas.
123 | passenger.info.reviews.amount.message=\nNúmero de avaliações para um passageiro: %s
124 |
125 | #PROFILE MESSAGES
126 | show.all.user.data.message = Os dados do seu perfil:\nNome: %s\nNúmero de telefone: %s\nOcultar número de telefone: %s
127 | edit.user.name.message = Quer mudar o seu nome? Ótimo!\nComo deseja ser chamado?
128 | edit.phone.number.message = Sem problema! Clique no botão para partilhar o seu número e eu adicioná-lo-ei instantaneamente\uD83D\uDE09
129 | remove.phone.number.message = Vejo que o seu número já foi adicionado \uD83E\uDD29\n\nPode apagá-lo ou apenas atualizá-lo, como preferir \uD83D\uDE09
130 | hidden.phone.number.false.message = O seu número de telefone está atualmente disponível para o passageiro/motorista contactar você.\n\nSe quiser alterar as configurações, pressione o botão "%s".
131 | hidden.phone.number.true.message = O seu número de telefone está atualmente oculto dos passageiros/motoristas, por isso eles não o verão se aceitarem o seu pedido.\n\nSe quiser alterar as configurações, pressione o botão "%s".
132 | successful.data.saved.message = Dados guardados com sucesso \uD83E\uDD73
133 | error.no.phone.number.message = Lamentamos, mas precisa de adicionar um número de telefone primeiro \uD83D\uDE14
134 | error.driver.need.exit.settings.menu.message = Infelizmente, não pode aceitar pedidos enquanto estiver no menu de configurações \uD83D\uDE14
135 | get.support.message = Pode sempre contactar-nos neste contacto com qualquer questão: @CompaneroSupport
136 |
137 |
138 | #MISC TEXT VALUES
139 | no.value = Não
140 | yes.value = Sim
141 | empty.value = -
142 | now.value = Agora
--------------------------------------------------------------------------------
/src/main/resources/localization_uk_UA.properties:
--------------------------------------------------------------------------------
1 | #HOOK MESSAGES
2 | authorize.as.passenger.hook.message = Я - найкращий пасажир
3 | authorize.as.driver.hook.message = Я - крутий водій
4 | confirm.arrival.hook.message = Я на місці
5 | create.new.order.hook.message = Почати пошук водія
6 | cancel.order.hook.message = Скасувати поїздку
7 | finish.order.hook.message = Завершити поїздку
8 | share.location.hook.message = Поділитись місцезнаходженням
9 | update.location.hook.message = Оновити своє місцезнаходження
10 | start.work.shift.hook.message = Шукати попутника
11 | stop.work.shift.hook.message = Припинити пошук попутника
12 | share.my.contact.hook.message = Поділитись своїм контактом
13 | skip.share.my.contact.hook.message = Пропустити крок
14 | add.notes.hook.message = Так, мені є що сказати
15 | skip.notes.hook.message = Ні, немає
16 | recommended.price.hook.message = %.2f
17 | confirm.order.hook.message = Підтвердити
18 | free.ride.hook.message = Халявна поїздка
19 | confirm.postponed.order.hook.message = Поїздка узгоджена
20 | decline.postponed.order.hook.message = Поїздка не узгоджена
21 |
22 | #USER SETTINGS HOOK MESSAGES
23 | open.settings.hook.message = Налаштування
24 | get.support.hook.message = Підтримка
25 | exit.settings.hook.message = Закрити налаштування
26 | back.to.previous.page.hook.message = Назад
27 | edit.user.name.hook.message = Змінити ім'я
28 | edit.phone.number.hook.message = Змінити номер телефону
29 | remove.phone.number.hook.message = Видалити номер телефону
30 | edit.share.phone.number.hook.message = Змінити скривання номеру
31 | reveal.phone.number.hook.message = Відображати номер
32 | hide.phone.number.hook.message = Скривати номер
33 |
34 |
35 | #INLINE TEXT
36 | write.to.passenger.inline.text = Чат із пасажиром
37 | write.to.driver.inline.text = Чат із водієм
38 | accept.inline.text = Взяти
39 | open.pickup.point.inline.text = Відкрити місце відправлення на мапі
40 | open.destination.point.inline.text = Відкрити пункт призначення на мапі
41 | wallet.inline.text=Гаманець
42 | add.postponed.departure.details.inline.text = Змінити час відправлення
43 |
44 |
45 | #MESSAGES
46 | user.policy.agreement.message=УВАГА: Використовуючи CompaneroBot, ти підтверджуєш, що прочитав і погодився з цією Угодою користувача та Політикою конфіденційності.
47 | request.contacts.message = Тепер, давай знайомитись!\n\nЯкщо бажаєш, ти можеш поділитись своїм номером телефону або пропустити цей крок.\n\nЖодна із цих опцій ніяк не вплине на твій досвід користування\uD83D\uDE09
48 | message.after.registration.with.phone.number = %s... Записую... В тебе чудове ім'я! Дуже приємно познайомитись!
49 | message.after.registration.without.phone.number = Без проблем! Ти в будь-який час зможеш його додати самостійно.
50 | message.missing.user.tag.general = Ще трошки уваги: \nМи поважаємо твою приватність, але, маємо повідомити, що через відсутність імені користувача (той, що починається з "@") в твоєму профілі Телеграм та відсутності номера телефону - у водія чи пасажира не буде змоги зв'язатись із тобою напряму у разі потреби.\n\nМи тебе не просимо щось із цього додавати, лише застерігаємо\uD83D\uDE09
51 | missing.user.tag.without.number.passenger.warn.message = Ще трошки уваги: \nМи поважаємо твою приватність, але, маємо повідомити, що через відсутність імені користувача (той, що починається з "@") в твоєму профілі Телеграм та відсутності/скритності номера телефону - у водія не буде змоги зв'язатись із тобою напряму у разі потреби.\n\nМи тебе не просимо щось із цього додавати, лише застерігаємо\uD83D\uDE09
52 | missing.user.tag.without.number.driver.warn.message = Ще трошки уваги: \nМи поважаємо твою приватність, але, маємо повідомити, що через відсутність імені користувача (той, що починається з "@") в твоєму профілі Телеграм та відсутності/скритності номера телефону - у пасажира не буде змоги зв'язатись із тобою напряму у разі потреби.\n\nМи тебе не просимо щось із цього додавати, лише застерігаємо\uD83D\uDE09
53 | financial.operations.warn.message = \n\nУВАГА: Ми ніяк не втручаємось в фінансові операції між водієм та пасажиром, питання оплати та його способу вирішується сторонами самостійно!
54 | incorrect.contact.message = На жаль, виглядає так, що отриманий контакт не співвідноситься до тебе.
55 | choose.role.message = Так, тепер, давай виберемо тобі роль! Ким хочеш бути?
56 | after.rate.message=Дякую за твій відгук! \u2764\uFE0F
57 | departure.time.order.message = \nЧас відправлення: %s
58 | order.price.message = \nЦіна: %.2f %s
59 | order.free.ride.message = \nЦя поїздка є БЕЗКОШТОВНОЮ
60 | phone.number.message = \nНомер телефону: +%s
61 | rating.message = \nРейтинг: %s/10
62 | further.contacts.postponed.message = \n\nТобі залишилось лише домовитись про усі деталі напряму.
63 | restricted.location.message=Схоже, що ми не працюємо в цьому регіоні. Будь ласка, оберіть інший.
64 | restricted.phone.number.message=Схоже, що ви використовуєте номер телефону з регіону з обмеженим доступом.\n\nБудь ласка, зареєструйтеся з іншим номером телефону, щоб мати повний доступ до функцій.
65 |
66 | #PASSENGER MESSAGES
67 | passenger.role.welcome.message=Добре! Тепер, коли потрібен буде тобі водій - натискай кнопку "%s"
68 | request.pickup.point.passenger.message=Добренько! Відправ мені, будь ласка, локацію, де тебе можна забрати?\n\nЯк надіслати локацію: \uD83D\uDCCE (Іконка вкладення) -> "Розташування" -> Вибрати місце відправлення на мапі
69 | request.destination.point.passenger.message=Записав. Тепер, відправ мені, будь ласочка, локацію, куди ти хочеш дібратись?\n\nЯк надіслати локацію: \uD83D\uDCCE (Іконка вкладення) -> "Розташування" -> Вибрати місце призначення на мапі
70 | ask.if.notes.needed.message = Готово. Скажи ще, будь ласка, чи є якісь особливі побажання? Можливо, тобі потрібна містка машина або тобі хочеться слухати п'єси Леся Подерв'янського по магнітолі?
71 | add.notes.message = Без проблем, кажи усі побажання, які вважаєш запотрібними :)
72 | add.price.order.message = За нашими підрахунками, рекомендована вартість поїздки - %.2f %s.\nТи можеш вказати власну ціну в місцевій валюті, написавши її прямо в чаті (напр. "5" або "5.50").\n\nАле, якщо у тебе немає можливості оплатити, натискай кнопку "Халявна поїздка" ;)
73 | price.error.more.than.int.max.message = На жаль, ви вказали більше, ніж максимально допустима вартість однієї поїздки.
74 | price.error.less.than.0.message = Вибачай, але від'ємну суму неможливо вказати :)
75 | price.error.other.message = Упс... Щось пішло не так. Спробуй ввести ціну у форматі, як на прикладі: "5" або "5.50"
76 | confirmation.passenger.order.base.message = Перевір, будь ласка, дані по своїй поїздці:\nМісце відправлення: %s\nМісце призначення: %s\nПримітки: %s
77 | confirmation.reminder.message = Якщо все вірно - можеш підтверджувати ;)
78 | confirm.order.by.passenger.message = Твій запит створено та відправлено усім водіям! Як тільки водій знайдеться - я тебе повідомлю ;)
79 | driver.info.base.message = Я знайшов для тебе найкращого водія!\n\nІм'я: %s
80 | driver.info.car.plate.message = \nАвтомобіль: %s, %s, %s
81 | driver.info.car.plate.postponed.message = \nАвтомобіль: %s
82 | driver.info.reviews.amount.message = \nКількість відгуків на водія: %s
83 | driver.info.missing.contacts.message = \n\nНа жаль, водій вирішив не надавати свої контакти для зв'язку із ним. Але він зможе зв'язатись із тобою, якщо твої контактні дані не приховані.
84 | driver.info.location.message = \n\nВодій скоро поділиться із тобою своєю локацією.
85 | driver.location.message = Водій знаходиться в %s км(-ів) від твого місця відправлення :)\n\nПриблизний час прибуття: %d хв(-ин)
86 | further.steps.for.passenger.postponed.message = Як домовитесь із водієм - натискай кнопку "%s", або тикай "%s" якщо потрібен буде інший.
87 | cancel.trip.by.passenger.self.message = Твоя поїздка скасована!\n\nЯк захочеш знайти водія наново - тицяй кнопку "%s" ;)
88 | driver.arrived.passenger.message = Твій водій вже на місці та чекає на тебе!
89 | finished.order.passenger.message = Твоя поїздка завершена!\n\nЯк захочеш знайти водія ще раз - тицяй кнопку "%s" ;)
90 | cancel.trip.by.driver.message = На жаль, схоже, що твого водія викрали прибульці, тому він не зможе приїхати :с\n\nАле ми вже відправили твій запит на поїздку іншим водіям ;)
91 | declined.postponed.trip.for.passenger.message = Шкода, що у вас не вийшло домовитись про поїздку із цим водієм :c\n\nАле не сумуй, ми вже відправили твій запит на поїздку іншим водіям ;)
92 | confirmed.postponed.trip.for.passenger.message = Я дуже радий, що у вас вийшло домовитись! Усю подальшу комунікацію ти можеш тримати із водієм напряму.\n\nЯк захочеш знайти водія ще раз - тицяй кнопку "%s" ;)
93 | add.review.on.driver.for.passengers.message=ID Замовлення: %s\nБудь ласка, розкажи нам, як пройшла твоя поїздка з водієм?
94 | payment.reminder.message = Будь ласка, не забудь оплатити поїздку після її закінчення.\nДо оплати: %.2f %s.\n\nЯкщо хочеш, можеш скористатись криптогаманцем в Телеграмі для переказу коштів водієві.
95 |
96 | #DRIVER MESSAGES
97 | request.driver.location.message = Будь ласка, поділись зі мною своїм місцезнаходженням, натиснувши відповідну кнопку.
98 | unavailable.order.message = На жаль, це замовлення більше не доступне. Будь ласка, обери інше.
99 | has.already.order.error.message = Вибач, але схоже, що у тебе ще є незавершені поїздки. Будь ласка, приймай нові поїздки тільки після того, як закінчиш поточну.
100 | order.id.part.message = ID Замовлення:
101 | new.order.base.message = ID Замовлення: %s\nМісце відправлення: %s\nПриблизний пункт призначення: %s\nДовжина поїздки: %s Км\nПримітки від пасажира: %s
102 | car.model.request.message = Хочеш бути водієм? Крутяк! Скажи мені, будь ласка, яка в тебе марка автомобіля?
103 | location.sent.to.passenger.message = Твоє місцезнаходження відправлено пасажиру, дякую!
104 | passenger.info.base.message = Ось трошки інформації про твого пасажира:\n\nІм'я: %s
105 | passenger.info.reviews.amount.message = \nКількість відгуків на пасажира: %s
106 | passenger.info.missing.contacts.message = \n\nНа жаль, пасажир вирішив не надавати свої контакти для зв'язку із ним. Але він зможе зв'язатись із тобою, якщо твої контактні дані не приховані.
107 | further.steps.for.driver.postponed.message = Як домовитесь із пасажиром - натискай кнопку "%s", або тикай "%s" якщо це замовлення тобі не підходить.
108 | future.arrival.reminder.message = Коли прибудеш на місце відправлення, будь ласка, натисни кнопку "%s"
109 | cancel.trip.by.passenger.message = На жаль, схоже, що твого пасажира викрали прибульці, тому він змушений був скасувати поїздку :с\n\nАле не сумуй, зараз ти будеш отримувати нові запити!
110 | stop.shift.message = Як захочеш закінчити отримувати нові пропозиції - натискай кнопку "%s"
111 | start.shift.message = Як захочеш почати отримувати нові пропозиції - натискай кнопку "%s"
112 | car.color.request.message = Чудова бі-біпка! А який колір в неї?
113 | car.plate.number.request.message = Майже мій улюбленний колір!\n\nВкажи ще, будь ласка, свій номер автомобіля :)
114 | driver.location.request.message=І останнє, будь ласка, надішли мені точку на карті, де ти хотів би отримувати запити від пасажирів.\n\nТи будеш отримувати запити на поїздки в районі 25 км від тебе для негайних поїздок, і 125 км від тебе для поїздок, які будуть замовлені заздалегідь.\n\nПросто натискай кнопку "%s" або відправ локацію, яка тобі потрібна. У будь-якому разі, потім ти зможеш її оновити у разі чого ;)
115 | car.info.registration.finished.message = Так, із реєстрацією твоєї машини ми закінчили. Мої вітання!\n\nТепер, тут ти будеш отримувати нові запити на поїздки від пасажирів.
116 | destination.point.driver.message = Я повідомив пасажира, що ти на місці.\n\nПункт призначення: %s\n\nТи можеш відкрити його на мапі, натиснувши кнопку трохи нижче ;)
117 | future.finish.order.reminder.message = Коли дістанешся пункту призначення - натискай кнопку "%s"
118 | finished.order.driver.message = Твоя поїздка завершена!\n\nЗараз ти будеш отримувати нові пропозиції.
119 | cancel.trip.by.driver.self.message = Твоя поїздка скасована!\n\nЗараз ти будеш отримувати нові пропозиції.
120 | declined.postponed.trip.for.driver.message = Шкода, що у вас не вийшло домовитись про поїздку із пасажиром :c\n\nАле не сумуй, зараз ти будеш отримувати нові пропозиції!
121 | confirmed.postponed.trip.for.driver.message = Я дуже радий, що у вас вийшло домовитись! Усю подальшу комунікацію ти можеш тримати із пасажиром напряму.\n\nА зараз ти будеш отримувати нові пропозиції!
122 | departure.details.message = Якщо тобі потрібна машина на конкретну дату і час - вкажи, будь ласка, ці деталі тут \uD83D\uDE4F
123 | add.review.on.passenger.for.drivers.message=ID Замовлення: %s\nБудь ласка, розкажи нам, як пройшла твоя поїздка з пасажиром?
124 |
125 | #PROFILE MESSAGES
126 | show.all.user.data.message = Дані твого профілю:\nІм'я: %s\nНомер телефону: %s\nСкривати номер: %s
127 | edit.user.name.message = Хочеш змінити ім'я? Чудово!\nЯк ти хочеш, щоб тебе кликали?
128 | edit.phone.number.message = Без проблем! Натискай кнопку, щоб поділитись своїм номером і я моментально його додам\uD83D\uDE09
129 | remove.phone.number.message = Я бачу, що твій номер вже доданий \uD83E\uDD29\n\nТи можеш видалити його або просто оновити, як тобі зручніше \uD83D\uDE09
130 | hidden.phone.number.false.message = Наразі твій номер телефону відкритий для водія/пасажира, щоб він міг із тобою зв'язатись.\n\nЯкщо хочеш змінити налаштування - тицяй на кнопку "%s".
131 | hidden.phone.number.true.message = Наразі твій номер телефону прихований від водія/пасажира, він не буде бачити його.\n\nЯкщо хочеш змінити налаштування - тицяй на кнопку "%s".
132 | successful.data.saved.message = Дані успішно збережені \uD83E\uDD73
133 | error.no.phone.number.message = Вибачай, але спочатку тобі потрібно додати номер телефону \uD83D\uDE14
134 | error.driver.need.exit.settings.menu.message = На жаль, ти не можеш приймати замовлення, поки знаходишся в налаштуваннях \uD83D\uDE14
135 | get.support.message = Ти завжди можеш до нас звернутись за цим контактом із будь-яким питанням: @CompaneroSupport
136 |
137 |
138 | #MISC TEXT VALUES
139 | no.value = Ні
140 | yes.value = Так
141 | empty.value = -
142 | now.value = Зараз
--------------------------------------------------------------------------------
/system.properties:
--------------------------------------------------------------------------------
1 | java.runtime.version=21
--------------------------------------------------------------------------------