Pavel Belyaev 2 years ago
commit f63ad619c5

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>HomeBot</artifactId>
<version>1.0-SNAPSHOT</version>
<name>HomeBot</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20230618</version>
</dependency>
<dependency>
<groupId>com.github.demidko</groupId>
<artifactId>aot</artifactId>
<version>2022.11.28</version>
</dependency>
<!-- хз-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-numbers-core</artifactId>
<version>1.1</version>
</dependency>
<!-- хз-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>org.example.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: org.example.App

@ -0,0 +1,132 @@
package org.example;
import org.pavlik.bot.*;
import org.pavlik.helpers.CoreHelp;
import org.pavlik.helpers.Morph;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Deque;
import java.util.HashMap;
import java.util.Properties;
public class App
{
protected static String tgToken;
protected static TelegramAdapter tgAdapter;
public static boolean stop_signal=false;
public static BotDialogController botDialogController = null;
public static BotCommands botCommands = null;
public static String admin_chat;
public static HashMap<String, BotDialog> Dialogs = new HashMap<>();
public static void loadConf() {
File file = new File("settings.properties");
Properties properties = new Properties();
try {
properties.load(new FileReader(file));
} catch (IOException e) {
System.out.println("файл с настройками не грузанулся");
throw new RuntimeException(e);
}
tgToken = properties.getProperty("tg.token");
admin_chat = properties.getProperty("tg.admin_id");
System.out.println("tgTokenLoaded");
}
public static void printStat() {
Runtime runtime = Runtime.getRuntime();
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
long usedMemory = totalMemory - freeMemory;
System.out.println("Total memory: " + totalMemory);
System.out.println("Free memory: " + freeMemory);
System.out.println("Used memory: " + usedMemory);
//String path = System.getProperty("user.dir");
}
public static void initApp() {
loadConf();
App.botDialogController = new BotDialogController();
App.botCommands = new BotCommands();
tgAdapter = new TelegramAdapter(tgToken);
startMsg();
}
//сообщение о запуске админу
public static void startMsg(){
String res = null;
while (res==null) {
CoreHelp.sleep(5000);
res = tgAdapter.sendMessage(admin_chat,"Я родился!");
}
}
/**
* Вытащить в асинхрон заполнение очереди и разгребание
*
* @param args
*/
public static void main( String[] args )
{
initApp();
while (!stop_signal) {
Long offset = tgAdapter.last_update + 1;
Deque<MessageObj> out = tgAdapter.getUpdates(offset.toString());
//если проблемы с соединением, то поспать 5 секунд и повторить...
if (out==null) {
System.out.println("result error");
CoreHelp.sleep(5000);
continue;
}
if (out.size()>0) {
while(!out.isEmpty()) {
MessageObj r = out.pop();
if (r.message_id.isEmpty()) continue;
if (!Dialogs.containsKey(r.message_id)) {
Dialogs.put(r.message_id, new BotDialog(tgAdapter));
}
App.botDialogController.answer(Dialogs.get(r.message_id),r);
}
}
}
}
}

@ -0,0 +1,88 @@
package org.pavlik.bot;
import org.example.App;
import org.apache.commons.lang3.math.NumberUtils;
public class BotCommands {
public String runCmd(BotDialog dialog, MessageObj r) {
String cmd1 = r.text.replaceAll("^/","");
String cmd0 = dialog.lastCmd;
String cmd = (cmd0 !=null && !cmd0.isEmpty()) ? cmd0 : cmd1;
switch (cmd) {
case ("stop"):
return this.cmdStop(dialog, cmd1);
case ("start"):
return "start";
case ("summ"):
return this.cmdSumm(dialog,cmd1);
case("no"):
return "выражайся четче, я твои команды не пойму!";
}
return "Неизвестная команда: "+cmd+" для справки введите /help";
}
protected String cmdStop(BotDialog dialog, String cmd) {
if (!dialog.is_admin) return "В доступе отказано";
if (cmd.equals("stop") && dialog.lastCmd==null) {
dialog.lastCmd=cmd;
return "Ты хочешь остановить бота, он умрет, если ты уверен, то ответь /yes или /no для отмены";
}
if (cmd.equals("yes")) {
App.stop_signal=true;
return "Аааааа, я подыхаю, всё, ты меня убил....\n Программа завершила свою работу.";
}
if (cmd.equals("no")) {
App.stop_signal=true;
dialog.lastCmd=null;
return "Ура, я жив, процесс убийства бота отменен.";
}
return "Вводи или /yes или /no других путей нет!!!";
}
protected String cmdSumm(BotDialog dialog, String cmd) {
if (dialog.lastCmd==null) {
dialog.lastCmd=cmd;
return "Запущен навык сумма, вводите числа и в конце напишите /res";
}
if (cmd.equals("res")) {
//return "Да я хз, что я Архимед????";
dialog.lastCmd=null;
return "Общая сумма:"+dialog.summ;
}
cmd = cmd.replace(",",".").trim();
if (NumberUtils.isParsable(cmd)) {
double ent = Double.parseDouble(cmd);
dialog.summ+=ent;
return "Число "+ent+" добавлено\nтекущая сумма:"+dialog.summ+"\nдля завершения рассчетов введи /res";
}
return "Я таких чисел понять не могу, можешь нормально ввести???";
}
}

@ -0,0 +1,22 @@
package org.pavlik.bot;
import org.example.App;
public class BotDialog {
public String lastName, firstName, userName, userId;
public boolean is_admin = false;
public String transportId;
public MessageAdapter adapter;
public boolean zdorova;
public boolean answName;
public String lastCmd;
public int cmdStage=0;
public double summ=0.0;
public BotDialog (MessageAdapter adapter) {
this.adapter = adapter;
}
}

@ -0,0 +1,69 @@
package org.pavlik.bot;
import org.example.App;
public class BotDialogController {
public void answer(BotDialog dialog, MessageObj r)
{
dialog.is_admin = checkAdmin(r);
String response = genResponse(r,dialog);
if (response!=null && !response.isEmpty() && !r.message_id.isEmpty()) {
dialog.adapter.sendMessage(r.message_id, response);
}
}
/**
* Генерация ответа на сообщение
* @param r - request, объект входящего сообщения с данными о пользователе, об объектах в сообщении
* @param dialog - контекст диалога с конкретным собеседником
* @return - текстовая строка с ответом на сообщение
*/
protected String genResponse(MessageObj r, BotDialog dialog) {
if (r.text == null) {
return "Ты шлешь мне какую-то дичь, еще раз пришлешь, не буду с тобой разговаривать.";
}
if (!r.text.isEmpty()) {
if (r.is_command || dialog.lastCmd!=null) {
//обработчик команд
return App.botCommands.runCmd(dialog,r);
}
else {
return govorilka(r,dialog);
}
}
return "";
}
protected String govorilka(MessageObj r, BotDialog dialog) {
if (!dialog.zdorova) {
dialog.zdorova = true;
return "Здарова, давай поговорим, скажи как к тебе обращаться?";
}
if (!dialog.answName) {
dialog.answName = true;
dialog.userName = r.text;
return "Хорошо, "+dialog.userName+", так и буду тебя называть!!!";
}
return dialog.userName+", на твое сообщение <"+r.text+"> я пока ответов не знаю, я маленький и глупый...";
}
protected boolean checkAdmin(MessageObj r) {
return r.message_id.equals("1187023222") && r.user_id.equals("pavelbbb");
}
}

@ -0,0 +1,9 @@
package org.pavlik.bot;
import java.util.Deque;
public interface MessageAdapter {
String sendMessage(String chatId, String text);
Deque<MessageObj> getUpdates(String offset);
}

@ -0,0 +1,9 @@
package org.pavlik.bot;
public class MessageObj {
public String text;
public String message_id;
public Long update_id;
public boolean is_command=false;
public String user_id;
}

@ -0,0 +1,130 @@
package org.pavlik.bot;
//import java.math.BigInteger;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.Deque;
import org.json.*;
import org.pavlik.helpers.RestHelper;
public class TelegramAdapter implements MessageAdapter {
String token;
RestHelper Rest;
public Long last_update = 0l;
protected String qUrl;
/**
* добавить исключение при пустом токене
* @param token
*/
public TelegramAdapter(String token) {
this.token = token;
this.Rest = new RestHelper();
qUrl = "https://api.telegram.org/bot"+token;
}
@Override
public String sendMessage(String chatId, String text) {
String encodedMsg = null;
try {
encodedMsg = URLEncoder.encode(text, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
String queryUrl = qUrl+"/sendMessage?chat_id="+chatId+"&text="+encodedMsg;
String respBody = Rest.queryGetBody(queryUrl);
System.out.println("--------------------------\n send message("+chatId+"):\n"+text);
return respBody;
}
/**
* добавить маскирование токена
* @param offset
* @return
*/
@Override
public Deque<MessageObj> getUpdates(String offset) {
String queryUrl = qUrl+"/getUpdates?offset="+offset+"&limit=10&timeout=60";
String respBody = Rest.queryGetBody(queryUrl);
System.out.println("-----------------------------------------");
System.out.println(respBody);
System.out.println("-----------------------------------------");
if (respBody == null) return null;
return parseResp(respBody);
}
protected Deque parseResp(String jsonBody) {
JSONObject obj = new JSONObject(jsonBody);
Deque<MessageObj> list = new ArrayDeque<>();
if (obj.getBoolean("ok")) {
JSONArray res_obj = obj.getJSONArray("result");
for (int i = 0; i < res_obj.length(); i++) {
JSONObject curr = res_obj.getJSONObject(i);
MessageObj r = new MessageObj();
Long update_id = curr.getLong("update_id");
last_update = update_id;
if (!curr.has("message")) continue;
JSONObject message = curr.getJSONObject("message");
JSONObject from = message.getJSONObject("from");
String chat_id = from.getBigInteger("id").toString();
if (message.has("text")) {
r.text = message.getString("text");
}
if (from.has("username"))
r.user_id = from.getString("username");
//detect command
if (message.has("entities")) {
JSONArray entities = message.getJSONArray("entities");
for (int e=0;e<entities.length();e++) {
JSONObject entities_it = entities.getJSONObject(e);
if (entities_it.has("type") && entities_it.getString("type").equals("bot_command")) {
r.is_command=true;
System.out.println("bottt!");
}
}
}
r.message_id = chat_id;
r.update_id = update_id;
//r.text = text;
list.add(r);
}
}
return list;
}
}

@ -0,0 +1,15 @@
package org.pavlik.helpers;
public class CoreHelp {
/**
* поспать msec 5000 = 5 sec
* @param msec - милисекунды
*/
public static void sleep(int msec) {
try {
Thread.sleep(msec);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

@ -0,0 +1,4 @@
package org.pavlik.helpers;
public class FileHelper {
}

@ -0,0 +1,37 @@
import org.apache.http.HttpResponse;
import org.pavlik.helpers.RestHelper;
//package org.pavlik.helpers;
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
/*RestHelper Rest = new RestHelper(
"client-keystore3.jks",
"JKS",
"123321",
"2",
"truststore.jks",
"JKS",
"123321");*/
RestHelper Rest = new RestHelper(
"client1.p12",
"PKCS12",
"123321",
null
);
String queryUrl = "https://192.168.200.10/index.php?kokoko=1";
String queryBody = "{\"k\":\"val\"}";
HashMap<String,String> queryHeaders = new HashMap<>();
queryHeaders.put("CONTENT-TYPE","text/plain2; charset=UTF-8");
HttpResponse resp = Rest.queryPostRaw(queryUrl,queryBody,queryHeaders);
String respBody = Rest.getRespBody(resp);
System.out.println(respBody);
}
}

@ -0,0 +1,72 @@
package org.pavlik.helpers;
import com.github.demidko.aot.WordformMeaning;
import java.util.List;
import static com.github.demidko.aot.WordformMeaning.lookupForMeanings;
//import java.util.ArrayList;
//import java.util.List;
public class Morph {
public String[] message2words (String message) {
message = message.replaceAll("[^a-zA-Zа-яА-ЯёЁ]"," ");
message = message.replaceAll("\\s{2,}"," ");
return message.split(" ");
}
public String morphAnalyze1(String message) {
String[] wordArr = message2words(message);
String out="";
for (int i=0;i<wordArr.length;i++) {
out+=morph1(wordArr[i])+"\n";
}
return out;
}
public String morph1(String word) {
List<WordformMeaning> meanings = lookupForMeanings(word);
String out = "";
if (meanings.isEmpty()) {
out = "слова <"+word+"> не слыхал";
}
else {
out = word+": "+meanings.get(0).getMorphology().toString();
}
return out;
}
public void Morph(String word) {
List<WordformMeaning> meanings = lookupForMeanings(word);
System.out.println(meanings.size());
//out.println(meanings.size());
/* 1 */
System.out.println(meanings.get(0).getMorphology());
//meanings.get(0).getMorphology().
//meanings.
/* [С, мр, им, мн] */
System.out.println(meanings.get(0).getLemma());
/* человек */
for (WordformMeaning t : meanings.get(0).getTransformations()) {
System.out.println(t.toString() + " " + t.getMorphology());
}
}
}

@ -0,0 +1,185 @@
package org.pavlik.helpers;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.PrivateKeyStrategy;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import java.io.*;
import java.security.*;
import java.util.HashMap;
/**
* RestHelper by Pavel Belyaev
*/
public class RestHelper {
public String codepage="UTF-8";
protected HttpClient httpClient = null;
public RestHelper () {
this(null,"", "", "", null, "", "");
}
public RestHelper (String keypath,String keytype,String keypass, String keyAlias, String trustpath, String trusttype, String trustpass) {
boolean withTrust = false;
KeyStore truststore_material = null;
KeyStore keystore_material = (keypath !=null) ? this.readKeyStore(keypath, keytype, keypass) : null;
PrivateKeyStrategy privateKeyStrategy = keyAlias == null ? null : (aliases, socket) -> keyAlias;
if (trustpath !=null) {
truststore_material = this.readKeyStore(trustpath, trusttype, trustpass);
withTrust = true;
}
SSLContext sslContext = (withTrust) ?
genSSLContext(privateKeyStrategy,keystore_material,truststore_material,keypass) :
genSSLContextAllTrust(privateKeyStrategy,keystore_material,keypass);
int timeout=61;
RequestConfig reqConf = RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD)
.setConnectTimeout(timeout * 1000)
.setConnectionRequestTimeout(timeout * 1000)
.setSocketTimeout(timeout * 1000)
.build();
this.httpClient = HttpClients.custom().setSSLContext(sslContext).setDefaultRequestConfig(reqConf).build();
}
/**
* Only keystore init
* @param keypath
* @param keytype
* @param keypass
* @param keyAlias
*/
public RestHelper (String keypath,String keytype,String keypass, String keyAlias) {
this(keypath,keytype,keypass,keyAlias, null, null, null);
}
/**
* Подгружает файл JKS или PKCS12
* @param path - путь до jks/p12
* @param type - JKS или PKCS12
* @param pwd - пароль к хранилищу
* @return - хранилище для SSLContext
*/
protected KeyStore readKeyStore(String path, String type, String pwd) {
try {
FileInputStream KeyStoreFile = new FileInputStream(new File(path));
KeyStore keyStore = KeyStore.getInstance(type);
keyStore.load(KeyStoreFile, pwd.toCharArray());
return keyStore;
} catch (Exception e){
throw new RuntimeException(e);
}
}
/**
* mtls - взаимная аутентификация
* @return
*/
SSLContext genSSLContext (PrivateKeyStrategy privateKeyStrategy,KeyStore keyStore, KeyStore trustStore, String keypass) {
try {
return SSLContexts.custom()
.loadTrustMaterial(trustStore,null)
.loadKeyMaterial(keyStore, keypass.toCharArray(),privateKeyStrategy)
.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Аутентификация только клиента, серверный сертификат не проверяется
* @return
*/
SSLContext genSSLContextAllTrust (PrivateKeyStrategy privateKeyStrategy,KeyStore keyStore, String keypass) {
try {
return SSLContexts.custom()
.loadTrustMaterial(null, (x509CertChain, authType) -> true) //вариант принимающий всё
.loadKeyMaterial(keyStore, keypass.toCharArray(),privateKeyStrategy) // use null as second param if you don't have a separate key password
.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected void map2headers(HttpPost query,HashMap<String, String> HeaderMap) {
for (String key : HeaderMap.keySet()) {
query.setHeader(key,HeaderMap.get(key));
}
}
public String getRespBody(HttpResponse resp){
try {
HttpEntity entity = resp.getEntity();
String body = EntityUtils.toString(entity, this.codepage);
EntityUtils.consume(entity);
return body;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Отправляет запрос "как есть" строкой
* @param queryUrl - url
* @param queryBody - тело запроса
* @param headerMap - заголовки запроса
*/
public HttpResponse queryPostRaw(String queryUrl, String queryBody, HashMap<String, String> headerMap) {
HttpPost query = new HttpPost(queryUrl);
if (headerMap != null) this.map2headers(query, headerMap);
try {
query.setEntity(new StringEntity(queryBody,this.codepage)); //тело
return this.httpClient.execute(query);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public HttpResponse queryGet(String queryUrl) {
HttpGet httpGet = new HttpGet(queryUrl);
try {
//query.setEntity(new StringEntity(queryBody,this.codepage)); //тело
return this.httpClient.execute(httpGet);
} catch (Exception e) {
//throw new RuntimeException(e);
return null;
}
}
public String queryGetBody(String queryUrl) {
System.out.println("Query:"+queryUrl);
HttpResponse res = queryGet(queryUrl);
if (res==null) return null;
return getRespBody(res);
}
}

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: org.example.App

@ -0,0 +1 @@
https://github.com/AKuznetsov/russianmorphology

@ -0,0 +1,20 @@
package org.example;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/**
* Unit test for simple App.
*/
public class AppTest
{
/**
* Rigorous Test :-)
*/
@Test
public void shouldAnswerWithTrue()
{
assertTrue( true );
}
}
Loading…
Cancel
Save