Compare commits

..

344 Commits

Author SHA1 Message Date
fdff6c7178 Merge pull request #119 from InsanusMokrassar/10.9.0
10.9.0
2025-10-21 23:13:32 +06:00
636614e4e3 revert sqlite 2025-10-21 23:13:22 +06:00
9747bcd79d update dependencies 2025-10-21 23:12:35 +06:00
f8b7e261f4 start 10.9.0 2025-10-21 23:03:43 +06:00
0a5272b1c8 Merge pull request #118 from InsanusMokrassar/10.8.0
10.8.0
2025-09-04 17:31:52 +06:00
214403ee88 update dependencies 2025-09-04 17:30:46 +06:00
c19a4bbcf9 start 10.8.0 2025-09-04 17:22:51 +06:00
58ba7c1e32 update dependencies 2025-08-04 13:33:02 +06:00
431b1bf1f2 start 10.7.0 2025-08-04 13:19:26 +06:00
ad23cc9202 Update github_release.gradle 2025-06-27 10:03:30 +06:00
e9bf2dfc64 Update github_release.gradle 2025-06-27 09:57:22 +06:00
61ea5e93b3 Merge pull request #115 from InsanusMokrassar/10.6.0
10.6.0
2025-06-27 09:36:26 +06:00
ff0d819bd2 update nmcp config 2025-06-27 09:35:43 +06:00
1919d8840a update dependencies 2025-06-27 09:31:27 +06:00
98c539b198 update publication way 2025-06-16 17:18:37 +06:00
7e02bb3583 start 10.6.0 2025-06-16 17:14:09 +06:00
d6e10d1dd1 Merge pull request #114 from InsanusMokrassar/10.5.0
10.5.0
2025-04-30 13:29:34 +06:00
b30aee0109 update dependencies 2025-04-30 13:26:31 +06:00
be45f94070 start 10.5.0 2025-03-27 08:31:24 +06:00
485d0d1fbf Merge pull request #113 from InsanusMokrassar/10.4.0
10.4.0
2025-02-16 09:22:03 +06:00
69e97223ce update dependencies 2025-02-16 09:21:30 +06:00
f067033678 start 10.4.0 2025-02-16 09:19:24 +06:00
37920521a0 Merge pull request #112 from InsanusMokrassar/10.3.1
10.3.1
2025-01-29 14:29:07 +06:00
d78f8adbea Update CHANGELOG.md 2025-01-29 14:28:55 +06:00
487ce413f1 update dependencies 2025-01-29 12:04:12 +06:00
556ded1e84 start 10.3.1 2025-01-29 12:02:34 +06:00
605fb956a4 Merge pull request #111 from InsanusMokrassar/10.3.0
10.3.0
2024-12-08 15:00:54 +06:00
b907f8d53b update dependencies 2024-12-07 10:10:17 +06:00
2a0cd5d6a8 start 10.3.0 2024-12-07 10:09:23 +06:00
00f3485959 Merge pull request #110 from InsanusMokrassar/10.2.1
10.2.1
2024-12-03 11:30:48 +06:00
856ae65fa8 add support of subcontext initial actions 2024-12-03 11:28:07 +06:00
d9488f8ccd start 10.2.1 2024-12-03 09:18:07 +06:00
2f06a65cc6 Merge pull request #109 from InsanusMokrassar/10.2.0
10.2.0
2024-12-01 12:00:01 +06:00
f3e6b55861 update dependencies 2024-12-01 11:59:02 +06:00
7bdb525f01 start 10.2.0 2024-12-01 11:57:22 +06:00
e6a2add7f8 Merge pull request #108 from InsanusMokrassar/10.1.1
10.1.1
2024-11-11 16:05:46 +06:00
3d7cb28c92 update tgbotapi 2024-11-11 16:02:10 +06:00
81a1ed6613 start 10.1.1 2024-11-11 15:59:14 +06:00
b43efb4255 Merge pull request #107 from InsanusMokrassar/10.1.0
10.1.0
2024-11-04 22:11:56 +06:00
8d3d9f8c6a update dependencies 2024-11-04 22:05:24 +06:00
6cb241642b start 10.1.0 2024-11-04 22:00:01 +06:00
f551f471d9 Merge pull request #106 from InsanusMokrassar/10.0.0
10.0.0
2024-09-22 19:40:02 +06:00
4342e04e3f replace database extension into externded file 2024-09-22 19:39:45 +06:00
a7fe1e3d82 improve registerConfig 2024-09-22 18:33:22 +06:00
c2d6afccc2 add koin extensions for plugins 2024-09-22 18:12:46 +06:00
d928db7e74 rework of plagubot system 2024-09-22 15:29:17 +06:00
893f3a95a1 migration onto 10.0.0 2024-09-22 14:46:20 +06:00
f9b7d444a6 add note about startPlugin in setupBotPlugin 2024-09-22 13:33:53 +06:00
47f5086ebd Plugin#setupBotPlugin will call startPlugin by default 2024-09-22 13:32:59 +06:00
bc29d4f83a start 9.3.1 2024-09-22 13:32:09 +06:00
26b34a470b Merge pull request #104 from InsanusMokrassar/9.3.0
9.3.0
2024-09-14 21:21:52 +06:00
3b507a5668 a lot of improvements 2024-09-14 21:06:06 +06:00
bb06ba1ca7 Add opportunity to use config in setup bot client 2024-09-14 20:17:38 +06:00
d772d275b3 start 9.3.0 2024-09-14 20:17:10 +06:00
e1e7c7a547 Merge pull request #103 from InsanusMokrassar/9.2.0
9.2.0
2024-09-06 00:11:20 +06:00
d8403dd3b7 update dependencies 2024-09-06 00:09:41 +06:00
17ac66f7fe start 9.2.0 2024-09-06 00:05:26 +06:00
b23c9b755a Merge pull request #102 from InsanusMokrassar/9.1.0
9.1.0
2024-08-15 21:32:02 +06:00
629ff7ee4e update dependencies 2024-08-15 21:30:04 +06:00
666ba9926e start 9.1.0 2024-08-15 21:29:17 +06:00
995bce3885 Merge pull request #101 from InsanusMokrassar/9.0.0
9.0.0
2024-08-12 16:35:14 +06:00
d597539b9e update dependencies 2024-08-12 16:24:34 +06:00
c80a7a1bda start 9.0.0 2024-08-12 16:22:42 +06:00
bd20c2d60f Merge pull request #100 from InsanusMokrassar/8.5.1
8.5.1
2024-07-24 16:10:12 +06:00
cfd42af6bc update dependencies 2024-07-24 16:08:27 +06:00
5c39fd2491 start 8.5.1 2024-07-24 16:06:56 +06:00
745b9cad72 Merge pull request #99 from InsanusMokrassar/8.5.0
8.5.0
2024-07-11 23:03:40 +06:00
f39947edd6 update dependencies 2024-07-11 23:01:37 +06:00
cacc1ef828 start 8.5.0 2024-07-11 23:00:11 +06:00
136d106b4c Merge pull request #98 from InsanusMokrassar/8.4.0
8.4.0
2024-06-27 23:20:42 +06:00
ddd3854d78 update dependencies 2024-06-27 22:31:45 +06:00
1c2bcb6907 start 8.4.0 2024-06-27 22:29:07 +06:00
8bd80c1c0c Merge pull request #97 from InsanusMokrassar/8.3.0
8.3.0
2024-04-23 18:50:57 +06:00
2234ffd55d update gradle wrapper 2024-04-23 18:44:51 +06:00
1a9d8b0d5e update dependencies 2024-04-23 18:44:26 +06:00
e00f40d06a start 8.3.0 2024-04-23 18:37:33 +06:00
9883d2b3b1 Merge pull request #96 from InsanusMokrassar/8.2.0
8.2.0
2024-02-18 21:34:04 +06:00
bdfd3b816c update dependencies 2024-02-18 21:31:45 +06:00
dd37ae0f2f start 8.2.0 2024-02-18 21:27:22 +06:00
8efe977e76 Merge pull request #95 from InsanusMokrassar/8.1.1
8.1.1
2024-02-10 23:45:26 +06:00
8290a68654 update dependencies 2024-02-10 23:44:52 +06:00
493a18a0f7 start 8.1.1 2024-02-10 23:41:36 +06:00
36608937af Merge pull request #94 from InsanusMokrassar/8.1.0
8.1.0
2024-01-14 18:42:36 +06:00
1b1b069d93 integrate startup launcher 2024-01-14 18:33:41 +06:00
37b5b8e867 start 8.1.0 2024-01-14 18:21:26 +06:00
468310c819 Merge pull request #93 from InsanusMokrassar/8.0.0
8.0.0
2024-01-12 20:28:24 +06:00
0d27a4f6f7 update dependencies 2024-01-12 20:12:58 +06:00
f9d131866f start 8.0.0 2024-01-12 20:11:29 +06:00
451b2bbc39 Merge pull request #92 from InsanusMokrassar/7.4.2
7.4.2
2023-12-24 23:25:42 +06:00
d51e2d8e7c fix of #90 and #91 2023-12-24 23:24:04 +06:00
6c45a8c848 update dependencies 2023-12-24 23:17:29 +06:00
8a7e05580d start 7.4.2 2023-12-24 23:14:24 +06:00
8b78f2901f Merge pull request #89 from InsanusMokrassar/7.4.1
7.4.1
2023-12-10 14:47:39 +06:00
cad8743ced update dependencies and fill changelog 2023-12-10 14:46:13 +06:00
8f827e9f79 start 7.4.1 2023-12-10 14:34:52 +06:00
28039df992 Merge pull request #88 from InsanusMokrassar/7.4.0
7.4.0
2023-11-26 20:56:04 +06:00
18019c37ea remove expicit KSLog dependency 2023-11-26 19:29:29 +06:00
8a84f65a12 Update CHANGELOG.md 2023-11-26 19:02:00 +06:00
49f30ab939 Update libs.versions.toml 2023-11-26 18:52:26 +06:00
8a15deceb8 Update gradle.properties 2023-11-26 18:49:43 +06:00
ea3273c4cf Merge pull request #87 from InsanusMokrassar/7.3.0
7.3.0
2023-11-06 15:17:37 +06:00
439972e783 update dependencies 2023-11-05 20:52:30 +06:00
08907291c5 update dependencies 2023-11-05 19:34:43 +06:00
0f4819a83d start 7.3.0 2023-11-05 19:14:12 +06:00
7abdf18491 Merge pull request #86 from InsanusMokrassar/7.2.3
7.2.3
2023-10-11 15:31:46 +06:00
98a91ea357 update dependencies 2023-10-11 15:29:44 +06:00
934f603a8a 7.2.3 2023-10-11 15:23:23 +06:00
76e9cdae8d Merge pull request #85 from InsanusMokrassar/7.2.2
7.2.2
2023-10-01 15:59:58 +06:00
fbe166f2b4 get back koin dependency 2023-10-01 15:55:33 +06:00
30cf190461 conflicts resolvers customization 2023-10-01 15:28:00 +06:00
9d72d79321 start 7.2.2 2023-09-30 17:43:46 +06:00
33057dd2cb Merge pull request #84 from InsanusMokrassar/7.2.1
7.2.1
2023-09-29 22:58:51 +06:00
e1bb8e9799 update dependencies 2023-09-29 22:48:57 +06:00
fd5e979f11 start 7.2.1 2023-09-29 22:42:45 +06:00
20e1f042f1 Merge pull request #83 from InsanusMokrassar/7.2.0
7.2.0
2023-09-26 01:01:08 +06:00
0e65a425c3 Update CHANGELOG.md 2023-09-26 00:57:08 +06:00
517ab1e1a4 Update libs.versions.toml 2023-09-26 00:56:20 +06:00
977cf32669 update dependencies 2023-09-26 00:21:31 +06:00
5bd1916fb5 start 7.2.0 2023-09-26 00:11:41 +06:00
8c22b418f8 Merge pull request #82 from InsanusMokrassar/7.1.0
7.1.0
2023-08-20 14:41:16 +06:00
3663f987bc update dependencies 2023-08-20 14:38:05 +06:00
93d15af80d start 7.1.0 2023-08-20 14:35:29 +06:00
27c5f379a4 Merge pull request #81 from InsanusMokrassar/7.0.0
7.0.0
2023-07-01 16:20:14 +06:00
ae7a7b84ac fill changelog 2023-07-01 16:01:25 +06:00
5b98aef237 update dependencies 2023-07-01 15:52:08 +06:00
3755972394 start 7.0.0 2023-07-01 15:50:20 +06:00
5d5312c66f Merge pull request #80 from InsanusMokrassar/6.1.0
6.1.0
2023-06-19 23:27:16 +06:00
f79fef3dae update dependencies 2023-06-19 22:53:17 +06:00
2c8dc80eae start 6.1.0 2023-06-19 22:28:52 +06:00
a2a2fe7ef4 Merge pull request #79 from InsanusMokrassar/6.0.1
6.0.1
2023-06-03 21:36:06 +06:00
34cadab809 Update CHANGELOG.md 2023-06-03 01:06:41 +06:00
784e041519 Update libs.versions.toml 2023-06-03 01:01:57 +06:00
4784f05c8e Update gradle.properties 2023-06-03 01:00:18 +06:00
e89b0a6ba2 Merge pull request #78 from InsanusMokrassar/6.0.0
6.0.0
2023-05-31 07:11:04 +06:00
b48d278446 Update CHANGELOG.md 2023-05-31 07:09:31 +06:00
072a64362d Update libs.versions.toml 2023-05-31 07:09:05 +06:00
7715f519e3 update dependencies 2023-05-28 20:54:39 +06:00
7982f27217 start 6.0.0 2023-05-28 20:53:32 +06:00
eeb3ae1dbe Merge pull request #77 from InsanusMokrassar/5.1.3
5.1.3
2023-05-20 12:43:54 +06:00
8a73fda6fa Update libs.versions.toml 2023-05-20 01:35:52 +06:00
05e94249af Update CHANGELOG.md 2023-05-20 01:35:36 +06:00
74c36c66f1 Update libs.versions.toml 2023-05-20 01:34:26 +06:00
5153f732ce start 5.1.3 2023-05-20 01:33:49 +06:00
fb23e9be79 Merge pull request #76 from InsanusMokrassar/5.1.2
5.1.2
2023-05-06 13:53:17 +06:00
292640b465 update dependencies 2023-05-06 13:32:05 +06:00
a863d91bab start 5.1.2 2023-05-06 13:31:15 +06:00
d1064bb9cd Merge pull request #75 from InsanusMokrassar/5.1.1
5.1.1
2023-05-02 10:13:37 +06:00
a9c3b937e7 Update CHANGELOG.md 2023-05-02 10:12:52 +06:00
6757354652 Update libs.versions.toml 2023-05-02 01:52:23 +06:00
c65efb6ffb Update gradle.properties 2023-05-02 01:51:11 +06:00
f9cc279854 Merge pull request #74 from InsanusMokrassar/5.1.0
5.1.0
2023-04-22 21:29:28 +06:00
b2d00cb5ae Update CHANGELOG.md 2023-04-22 21:24:18 +06:00
782721751a Update libs.versions.toml 2023-04-22 21:12:16 +06:00
01086766ba Update gradle.properties 2023-04-22 21:10:47 +06:00
bf0a6ab659 Merge pull request #73 from InsanusMokrassar/5.0.2
5.0.2
2023-04-20 00:20:43 +06:00
a3e6f8a6b5 update dependencies 2023-04-20 00:18:24 +06:00
cd9ba5dc19 start 5.0.2 2023-04-20 00:15:37 +06:00
8e0d35a80d Merge pull request #72 from InsanusMokrassar/5.0.1
5.0.1
2023-03-16 20:29:57 +06:00
a49fb60555 Update CHANGELOG.md 2023-03-16 19:56:01 +06:00
ec26179d2a Update libs.versions.toml 2023-03-16 19:55:28 +06:00
daed26cba6 Update gradle.properties 2023-03-16 19:54:56 +06:00
7c820b70ac Merge pull request #71 from InsanusMokrassar/5.0.0
5.0.0
2023-03-12 00:07:27 +06:00
edb15f11db Update CHANGELOG.md 2023-03-12 00:06:55 +06:00
18000429b0 Update libs.versions.toml 2023-03-11 23:58:27 +06:00
d975e61966 start 2023-03-11 23:56:26 +06:00
663e00cad6 Merge pull request #70 from InsanusMokrassar/4.1.0
4.1.0
2023-03-08 22:27:47 +06:00
6725193545 Update CHANGELOG.md 2023-03-08 22:26:50 +06:00
ccfd91b1ac Update libs.versions.toml 2023-03-08 17:17:36 +06:00
c8b69d641f start 4.1.0 2023-03-08 17:16:31 +06:00
7af11fc427 Merge pull request #69 from InsanusMokrassar/4.0.3
4.0.3
2023-03-02 23:48:27 +06:00
59b91fc1ff Update CHANGELOG.md 2023-03-02 22:03:01 +06:00
4293096ed2 Update libs.versions.toml 2023-03-02 22:02:22 +06:00
42dd98426c start 4.0.3 2023-03-02 22:01:45 +06:00
744520c73f Merge pull request #68 from InsanusMokrassar/4.0.2
4.0.2
2023-03-01 15:45:17 +06:00
1b8ae09866 Update CHANGELOG.md 2023-03-01 15:36:55 +06:00
3027e39665 Update libs.versions.toml 2023-03-01 15:35:32 +06:00
b77fe446f8 start 4.0.2 2023-03-01 15:34:46 +06:00
bc11d7508f Merge pull request #67 from InsanusMokrassar/4.0.1
4.0.1
2023-02-28 21:08:39 +06:00
cd9af3c216 Update CHANGELOG.md 2023-02-28 20:05:35 +06:00
c60face0e6 Update libs.versions.toml 2023-02-28 20:01:47 +06:00
334ca1a184 start 4.0.1 2023-02-28 20:00:54 +06:00
b7bb6f10a9 Merge pull request #66 from InsanusMokrassar/4.0.0
4.0.0
2023-02-28 13:56:58 +06:00
7b14343cc5 update gradle wrapper 2023-02-28 11:41:29 +06:00
62c1f87e95 Update libs.versions.toml 2023-02-27 23:49:19 +06:00
317f15bbb8 start 4.0.0 2023-02-27 23:47:53 +06:00
34c0c05715 Merge pull request #65 from InsanusMokrassar/3.5.0
3.5.0
2023-02-17 15:58:32 +06:00
d23bde75b5 update dependencies 2023-02-17 14:08:36 +06:00
46e48efe52 start 3.5.0 2023-02-17 14:07:28 +06:00
1bf59c20d4 Merge pull request #64 from InsanusMokrassar/3.4.1
3.4.1
2023-02-12 01:35:21 +06:00
3592a5907c setupBotPlugin now works synchronously 2023-02-12 01:29:45 +06:00
328a8b215c start 3.4.1 2023-02-12 01:28:35 +06:00
57ba6411e4 Merge pull request #63 from InsanusMokrassar/3.4.0
3.4.0
2023-02-06 15:27:10 +06:00
4d53d2dc63 update dependencies 2023-02-06 14:12:23 +06:00
2671794f22 start 3.4.0 2023-02-06 14:10:34 +06:00
9eff09ca68 Merge pull request #62 from InsanusMokrassar/3.3.1
3.3.1
2023-01-19 00:23:12 +06:00
7f1d972105 Update CHANGELOG.md 2023-01-19 00:22:25 +06:00
d05413a54e Update libs.versions.toml 2023-01-19 00:15:29 +06:00
2342bd9a38 Update gradle.properties 2023-01-19 00:02:22 +06:00
c9a6df5614 Merge pull request #61 from InsanusMokrassar/3.3.0
3.3.0
2023-01-01 02:28:52 +06:00
295f1ce7ab Update CHANGELOG.md 2023-01-01 02:27:56 +06:00
4ca97546b5 Update libs.versions.toml 2023-01-01 02:26:42 +06:00
166dc4b729 Update gradle.properties 2023-01-01 02:25:30 +06:00
f09929648e Merge pull request #60 from InsanusMokrassar/3.2.3
3.2.3
2022-12-28 12:41:51 +06:00
7d906e0c9c Update CHANGELOG.md 2022-12-28 09:27:55 +06:00
dc32a4eb7f Update libs.versions.toml 2022-12-28 09:27:38 +06:00
5b5f95e0ec start 3.2.3 2022-12-28 09:27:04 +06:00
a0fd9012d2 Merge pull request #59 from InsanusMokrassar/3.2.2
3.2.2
2022-12-20 09:19:12 +06:00
14910ed568 Update CHANGELOG.md 2022-12-20 09:18:51 +06:00
ccc936f821 Update libs.versions.toml 2022-12-20 09:15:56 +06:00
877e693eb3 start 3.2.2 2022-12-20 09:13:35 +06:00
9f3634f2ec Merge pull request #58 from InsanusMokrassar/3.2.1
3.2.1
2022-12-08 11:05:38 +06:00
08d905805a Update CHANGELOG.md 2022-12-08 10:47:08 +06:00
92cf2167cd Update libs.versions.toml 2022-12-08 10:46:17 +06:00
3d6a208aa8 Update gradle.properties 2022-12-08 10:45:10 +06:00
6e61f364da Merge pull request #57 from InsanusMokrassar/3.2.0
3.2.0
2022-12-05 16:31:11 +06:00
399fcb8466 update dependencies 2022-12-05 15:45:55 +06:00
477d83e31b start 3.2.0 2022-12-05 15:31:19 +06:00
e761f84023 Merge pull request #56 from InsanusMokrassar/3.1.4
3.1.4
2022-11-28 18:12:36 +06:00
caca21fac9 Update CHANGELOG.md 2022-11-28 16:30:45 +06:00
4f2934fbae Update libs.versions.toml 2022-11-28 16:29:59 +06:00
8c3c52c92b Update gradle.properties 2022-11-28 16:29:11 +06:00
779b56394a Merge pull request #55 from InsanusMokrassar/3.1.3
3.1.3
2022-11-17 13:17:49 +06:00
3b11cdc2c6 update tgbotapi 2022-11-17 13:01:08 +06:00
1a823cda6f add own repo 2022-11-17 13:00:19 +06:00
6a29264caf start 3.1.3 2022-11-17 12:59:39 +06:00
4d32de8c2f add gitea publication 2022-11-17 11:29:02 +06:00
f7cce657a8 Merge pull request #54 from InsanusMokrassar/3.1.2
3.1.2
2022-11-15 17:31:44 +06:00
a4ca827a5c Update CHANGELOG.md 2022-11-15 11:28:43 +06:00
224107e35e Update libs.versions.toml 2022-11-15 09:58:30 +06:00
9efebd027d Update gradle.properties 2022-11-15 09:57:22 +06:00
841156e8b5 Merge pull request #53 from InsanusMokrassar/3.1.1
3.1.1
2022-11-15 02:16:21 +06:00
ab4d06a44c Update CHANGELOG.md 2022-11-15 02:15:06 +06:00
0766bf7d76 Update libs.versions.toml 2022-11-15 00:17:22 +06:00
f7c7e338e2 Update gradle.properties 2022-11-15 00:15:56 +06:00
6a4fed07ee Merge pull request #52 from InsanusMokrassar/3.1.0
3.1.0
2022-11-10 20:57:02 +06:00
88f5fbfd18 Update HelloPlugin.kt 2022-11-10 20:54:34 +06:00
f644817c04 Update HelloPlugin.kt 2022-11-10 20:53:12 +06:00
8a8eb3c3b7 Update CHANGELOG.md 2022-11-10 20:28:26 +06:00
8cb68495c9 Update libs.versions.toml 2022-11-10 20:26:28 +06:00
6f2c922edf start 3.1.0 2022-11-10 20:23:23 +06:00
5895335031 Merge pull request #51 from InsanusMokrassar/3.0.0
3.0.0
2022-11-09 01:14:24 +06:00
5f25250bcc Update CHANGELOG.md 2022-11-09 01:12:55 +06:00
f0d2a6d39d Update libs.versions.toml 2022-11-09 00:47:23 +06:00
3e4dc1fdb0 Update gradle.properties 2022-11-09 00:45:08 +06:00
55012eacec Merge pull request #50 from InsanusMokrassar/2.4.1
2.4.1
2022-11-03 12:41:13 +06:00
c64314fa11 update changelog 2022-11-03 12:24:42 +06:00
f0b7ae7325 update dependencies 2022-11-03 12:17:05 +06:00
4ade949593 start 2.4.1 2022-11-03 12:14:58 +06:00
2a9342e4c7 Merge pull request #49 from InsanusMokrassar/2.4.0
2.4.0
2022-10-22 22:04:32 +06:00
7d57ceafaa update dependencies 2022-10-22 21:58:33 +06:00
823a53d5aa start 2.4.0 2022-10-22 21:53:19 +06:00
c1889ceff0 Merge pull request #48 from InsanusMokrassar/2.3.4
2.3.4
2022-10-02 01:27:59 +06:00
40c4ae128f update dependencies 2022-10-01 03:00:29 +06:00
0f59009300 start 2.3.4 2022-10-01 00:32:21 +06:00
a273f1117f Merge pull request #47 from InsanusMokrassar/2.3.3
2.3.3
2022-09-19 20:44:51 +06:00
c8bb5e1195 Update CHANGELOG.md 2022-09-19 16:08:11 +06:00
fbd98d67a9 Update libs.versions.toml 2022-09-19 16:06:00 +06:00
2350555fbb start 2.3.3 2022-09-19 16:04:44 +06:00
4130f98caa Merge pull request #46 from InsanusMokrassar/2.3.2
2.3.2
2022-09-15 20:12:43 +06:00
f8161c34a7 update dependencies 2022-09-15 20:07:23 +06:00
6fe333e437 start 2.3.2 2022-09-15 20:05:31 +06:00
5806fa1c31 Merge pull request #45 from InsanusMokrassar/2.3.1
2.3.1
2022-09-09 13:44:37 +06:00
2ff712327f Update CHANGELOG.md 2022-09-09 04:22:56 +06:00
72e8e35e3f Update libs.versions.toml 2022-09-09 04:20:09 +06:00
030f9546f2 Update gradle.properties 2022-09-09 04:18:05 +06:00
1b3c479766 Merge pull request #44 from InsanusMokrassar/2.3.0
2.3.0
2022-09-04 16:10:09 +06:00
dcfb66ef6c fixes 2022-09-04 15:57:40 +06:00
763718716d improve reconnect feature 2022-09-04 15:07:30 +06:00
dfbc7be6f2 add option waitForConnection in database config 2022-09-04 14:37:44 +06:00
ab0578b312 start 2.3.0 2022-09-04 14:31:46 +06:00
7b502e073d Merge pull request #43 from InsanusMokrassar/2.2.0
2.2.0
2022-08-27 13:47:59 +06:00
137a6c1c26 update dependencies 2022-08-27 13:45:26 +06:00
74f1ad496e start 2.2.0 2022-08-27 13:43:51 +06:00
e4a1e1f0be Merge pull request #42 from InsanusMokrassar/2.1.1
2.1.1
2022-08-20 22:30:51 +06:00
7286cf401b make it possible to get bot from DI 2022-08-20 22:10:08 +06:00
cdf94ec2eb start 2.1.1 2022-08-20 22:08:13 +06:00
5bfabfa284 Merge pull request #41 from InsanusMokrassar/2.1.0
2.1.0
2022-08-18 12:43:39 +06:00
ec2852beb0 complete with including of FSM 2022-08-18 12:42:34 +06:00
6c2cfbf06f a little upgrade of hello plugin 2022-08-18 12:27:11 +06:00
caa028b799 Update CHANGELOG.md 2022-08-17 09:55:54 +06:00
53667fa8b8 Update libs.versions.toml 2022-08-16 00:50:12 +06:00
81ca68dc06 Update CHANGELOG.md 2022-08-14 00:10:45 +06:00
6f74e6b4cb fill readme + rename fallback state handler 2022-08-13 20:37:17 +06:00
7dad3581f1 fixes/fill of docs 2022-08-13 20:30:10 +06:00
751e9aa66c remove redundant modules 2022-08-13 20:09:21 +06:00
08b797bbc2 start integration FSM oriented plagubot version 2022-08-13 18:30:33 +06:00
fa00d11a39 update gradle wrapper 2022-08-13 18:09:38 +06:00
1ba3953dfa update dependencies 2022-08-13 18:09:19 +06:00
af86a64a48 start 2.1.0 2022-08-13 18:08:00 +06:00
60fe1b5df9 Update CHANGELOG.md 2022-08-06 01:10:41 +06:00
c50b35c66b Merge pull request #39 from InsanusMokrassar/2.0.0
2.0.0
2022-08-06 01:10:14 +06:00
b309d6c946 Update libs.versions.toml 2022-08-06 00:42:58 +06:00
4f2b0aa40c Update libs.versions.toml 2022-08-05 22:52:59 +06:00
2d38292b55 Update CHANGELOG.md 2022-08-05 22:11:37 +06:00
e177f3e47a Update libs.versions.toml 2022-08-05 22:08:01 +06:00
2872395045 start 2.0.0 2022-08-05 22:06:39 +06:00
e49302b750 Merge pull request #38 from InsanusMokrassar/1.4.1
1.4.1
2022-08-03 09:20:34 +06:00
60dac2067a Update CHANGELOG.md 2022-08-03 09:20:10 +06:00
fc1888923f Update libs.versions.toml 2022-08-01 09:33:27 +06:00
703d3b1d64 Update gradle.properties 2022-08-01 09:32:21 +06:00
34383c1f82 Merge pull request #37 from InsanusMokrassar/1.4.0
1.4.0
2022-07-30 20:32:21 +06:00
9ec5303aed Update CHANGELOG.md 2022-07-30 18:29:45 +06:00
351f6e59e1 Update libs.versions.toml 2022-07-30 18:29:26 +06:00
d4bc89eb2f start 1.4.0 and update kslog 2022-07-30 15:27:28 +06:00
00b8197b71 Merge pull request #36 from InsanusMokrassar/1.3.1
1.3.1
2022-07-22 21:11:52 +06:00
a090b4f13f Update CHANGELOG.md 2022-07-22 21:10:05 +06:00
b377b5ed4f Update dependencies 2022-07-22 20:03:24 +06:00
dde3317323 start 1.3.1 2022-07-22 20:02:33 +06:00
40de085f26 Merge pull request #35 from InsanusMokrassar/1.3.0
1.3.0
2022-07-11 12:32:34 +06:00
ce5b98d6c8 update kotlin 2022-07-11 12:27:55 +06:00
058c239690 start 1.3.0 2022-07-11 12:17:08 +06:00
43d49ac3cd Update CHANGELOG.md 2022-07-10 00:21:27 +06:00
b0fbcfd54f Merge pull request #34 from InsanusMokrassar/1.2.3
1.2.3
2022-07-10 00:20:53 +06:00
8f726cee82 start 1.2.3 and update tgbotapi 2022-07-09 23:11:29 +06:00
998968a9c1 Update github_release.gradle 2022-07-09 09:47:34 +06:00
d8d1860c5a Merge pull request #33 from InsanusMokrassar/1.2.2
1.2.2
2022-07-09 09:44:56 +06:00
7ffd5a1433 update dependencies 2022-07-09 00:12:24 +06:00
05e2ec1c0d start 1.2.2 2022-07-09 00:07:07 +06:00
819ed7720a Merge pull request #32 from InsanusMokrassar/1.2.1
1.2.1
2022-06-26 15:15:38 +06:00
c99e4ee188 Update CHANGELOG.md 2022-06-26 14:46:09 +06:00
a408cc5099 Update CHANGELOG.md 2022-06-26 14:45:55 +06:00
f1d3f48a6b Update libs.versions.toml 2022-06-26 14:44:13 +06:00
2777a260ae Update gradle.properties 2022-06-26 14:42:44 +06:00
155b9865a8 Merge pull request #31 from InsanusMokrassar/1.2.0
1.2.0
2022-06-22 09:05:33 +06:00
ecc17e50b9 update dependencies 2022-06-21 23:54:25 +06:00
ffafee3f43 start 1.2.0 2022-06-21 23:53:38 +06:00
b99bb9ee64 Merge pull request #30 from InsanusMokrassar/1.1.2
1.1.2
2022-06-20 20:59:53 +06:00
0dff596926 update dependencies and optimize imports 2022-06-20 20:58:38 +06:00
e0a19bb5e5 start 1.1.2 + add opportunity to load object plugins 2022-06-20 20:52:42 +06:00
5ec1c8c55f Merge pull request #29 from InsanusMokrassar/1.1.1
1.1.1
2022-06-11 19:20:33 +06:00
37fd9f39d3 fixes in logging 2022-06-11 19:19:19 +06:00
f9f56f6afb update dependencies and add logging 2022-06-11 19:15:09 +06:00
343c26a7f1 start 1.1.1 2022-06-08 17:14:50 +06:00
1b5361eb28 change version in properties 2022-06-08 17:13:46 +06:00
511ec904e9 start 1.1.0 and update tgbotapi 2022-06-08 17:13:46 +06:00
a3f59087e0 updates in dependencies and update bot setup logic 2022-06-08 17:13:46 +06:00
492c04e25f start 1.0.1 2022-06-08 17:13:46 +06:00
6b017c129f remove redundant config test and update build workflow 2022-06-08 17:13:46 +06:00
93829d3e0d add logging inside of plagubot 2022-06-08 17:13:46 +06:00
a5e7ac180d fill changelog 2022-06-08 17:13:46 +06:00
77ba1d686c complete 1.0.0 2022-06-08 17:13:46 +06:00
dec27b1c34 temporal progress 2022-06-08 17:13:46 +06:00
11c5a38b72 start migration 2022-06-08 17:13:46 +06:00
9521217765 start 1.0.0 2022-06-08 17:13:46 +06:00
39 changed files with 1416 additions and 531 deletions

0
.fleet/settings.json Normal file
View File

View File

@@ -8,9 +8,9 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
- name: Set up JDK 17
uses: actions/setup-java@v1
with:
java-version: 1.8
java-version: 17
- name: Build with Gradle
run: ./gradlew build

2
.gitignore vendored
View File

@@ -10,5 +10,7 @@ build/
out/
local.properties
local.*
local.*/
config.json
secret.gradle

View File

@@ -1,5 +1,668 @@
# Changelog
## 10.9.0
* `Versions`:
* `kotlin`: `2.2.20`
* `microutils`: `0.26.6`
* `tgbotapi`: `30.0.0`
* `koin`: `4.1.1`
## 10.8.0
* `Versions`:
* `kotlin`: `2.2.10`
* `microutils`: `0.26.3`
* `tgbotapi`: `28.0.1`
## 10.7.0
* `Versions`:
* `kotlin`: `2.2.0`
* `serialization`: `1.9.0`
* `microutils`: `0.26.2`
* `tgbotapi`: `27.1.1`
* `koin`: `4.1.0`
## 10.6.0
* `Versions`:
* `microutils`: `0.25.8`
* `tgbotapi`: `26.0.0`
* `sqlite`: `3.50.1.0`
## 10.5.0
* `Versions`:
* `kotlin`: `2.1.20`
* `serialization`: `1.8.1`
* `coroutines`: `1.10.2`
* `microutils`: `0.25.5`
* `tgbotapi`: `24.0.2`
* `exposed`: `0.61.0`
* `sqlite`: `3.49.1.0`
* `koin`: `4.0.4`
## 10.4.0
* `Versions`:
* `microutils`: `0.24.6`
* `tgbotapi`: `23.2.0`
* `exposed`: `0.59.0`
* `sqlite`: `3.49.0.0`
## 10.3.1
* `Versions`:
* `kotlin`: `2.1.10`
* `serialization`: `1.8.0`
* `coroutines`: `1.10.1`
* `microutils`: `0.24.5`
* `tgbotapi`: `23.1.2`
* `exposed`: `0.58.0`
* `sqlite`: `3.48.0.0`
* `koin`: `4.0.2`
## 10.3.0
* `Versions`:
* `microutils`: `0.23.2`
* `tgbotapi`: `22.0.0`
* `exposed`: `0.57.0`
## 10.2.1
* `Versions`:
* `tgbotapi`: `21.0.1`
* `Bot`:
* Now all `CombinedSubcontextInitialAction.SubItem`s will be taken from `Koin` to setup root `subcontextInitialAction`
## 10.2.0
* `Versions`:
* `kotlin`: `2.1.0`
* `microutils`: `0.23.1`
* `tgbotapi`: `21.0.0`
* `exposed`: `0.56.0`
* `sqlite`: `3.47.1.0`
## 10.1.1
* `Versions`:
* `tgbotapi`: `20.0.1`
## 10.1.0
* `Versions`:
* `kotlin`: `2.0.21`
* `serialization`: `1.7.3`
* `coroutines`: `1.9.0`
* `microutils`: `0.23.0`
* `tgbotapi`: `20.0.0`
* `exposed`: `0.55.0`
* `sqlite`: `3.47.0.0`
* `koin`: `4.0.0`
## 10.0.0
**OVERALL LOGIC OF PLAGUBOT INITIALIZATION AND WORK HAS BEEN CHANGED**
First of all, since this update `PlaguBot` will use default `StartPlugin` logic and will be built on top of it.
All special methods of `Plugin` will be called from one of `PlaguBot` initialization phases:
* `setupBotClient` will be called from `single` initialization of `telegramBot` (in `setupDI` phase)
* `setupBotPlugin` will be called from `startPlugin` method in time of `buildBehaviourWithFSM` initialization
* `Plugin`:
* Extension `Module.setupDI(Database,JsonObject)` has been dropped. Use `database` extension in `Module.setupDI(JsonObject)`
* `Bot`:
* `dev.inmo.plagubot.config.Config` lost its `plugins` section. Now you may retrieve plugins from `Koin` only
* `defaultJsonFormat` became `Warning` feature due to the fact of its fully default nature
* `PlaguBot` lost old `start` method and took two new: with `args` as `Array<String>` and `initialConfig` as `JsonObject`
**Migration:**
* If you are running bot and doing it using `StartPlugin` launcher, add `dev.inmo.plagubot.PlaguBot` explicitly
* In plugins: replace your `setupDI` overrides with `Database` as argument by the same one, but `database` will be
available as extension in `single` or `factory` calls (as extension to `Scope` and `Koin`)
## 9.3.0
* `Bot`:
* Now bot is not built-in into `PlaguBot` and setted up as all other `Koin` dependencies
* Now it is possible to use `testServer` parameter for bots out of the box
* `Plugin`:
* New method `setupBotClient` with arguments to let plugin setup bot more freely
## 9.2.0
* `Versions`:
* `kotlin`: `2.0.20`
* `serialization`: `1.7.2`
* `microutils`: `0.22.2`
* `tgbotapi`: `18.1.0`
* `exposed`: `0.54.0`
* `sqlite`: `3.46.1.0`
## 9.1.0
* `Versions`:
* `tgbotapi`: `17.0.0`
## 9.0.0
* `Versions`:
* `Kotlin`: `2.0.10`
* `Serialization`: `1.7.1`
* `MicroUtils`: `0.22.0`
* `tgbotapi`: `16.0.0`
* `Exposed`: `0.53.0`
## 8.5.1
* `Versions`:
* `MicroUtils`: `0.21.4`
* `tgbotapi`: `15.2.0`
## 8.5.0
* `Versions`:
* `MicroUtils`: `0.21.2`
* `tgbotapi`: `15.1.0`
## 8.4.0
* `Versions`:
* `Coroutines`: `1.8.1`
* `MicroUtils`: `0.21.1`
* `tgbotapi`: `15.0.0`
* `Exposed`: `0.51.1`
## 8.3.0
* `Versions`:
* `Serialization`: `1.6.3`
* `MicroUtils`: `0.20.45`
* `tgbotapi`: `12.0.1`
* `Exposed`: `0.49.0`
* `SQLite`: `3.45.3.0`
* `Koin`: `3.5.6`
## 8.2.0
* `Versions`:
* `Coroutines`: `1.8.0`
* `tgbotapi`: `10.1.0`
* `MicroUtils`: `0.20.35`
## 8.1.1
* `Versions`:
* `tgbotapi`: `10.0.1`
* `MicroUtils`: `0.20.32`
* `Exposed`: `0.47.0`
## 8.1.0
* Integrate `dev.inmo:micro_utils.startup` into project
## 8.0.0
* `Versions`:
* `tgbotapi`: `10.0.0`
* `MicroUtils`: `0.20.26`
* `Exposed`: `0.46.0`
## 7.4.2
* `Versions`:
* `Kotlin`: `1.9.22`
* `tgbotapi`: `9.4.3`
* `MicroUtils`: `0.20.23`
* `Koin`: `3.5.7`
## 7.4.1
* `Versions`:
* `Serialization`: `1.6.2`
* `tgbotapi`: `9.4.2`
* `Exposed`: `0.45.0`
* `SQLite`: `3.44.1.0`
* `MicroUtils`: `0.20.19`
* `uuid`: `0.8.2`
* `ktor`: `2.3.7`
## 7.3.0
* `Versions`:
* `Kotlin`: `1.9.21`
* `Serialization`: `1.6.1`
* `tgbotapi`: `9.4.1`
* `ktor`: `2.3.6`
* `KSLog`: Removed explicit dependency, now it is declared in tgbotapi
* `MicroUtils`: `0.20.15`
## 7.2.3
* `Versions`:
* `tgbotapi`: `9.2.2`
* `exposed`: `0.44.0`
* `koin`: `3.5.0`
* `ktor`: `2.3.5`
## 7.2.2
* `Bot`:
* Now you may customize both `onStart` and `onUpdate` conflicts resolvers
## 7.2.1
* `Versions`:
* `tgbotapi`: `9.2.1`
* `ktor`: `2.3.4`
## 7.2.0
* `Version`:
* `tgbotapi`: `9.2.0`
* `kslog`: `1.1.2`
* `sqlite`: `3.43.0.0`
## 7.1.0
* `Version`:
* `microutils`: `0.19.9`
* `tgbotapi`: `9.1.0`
* `ktor`: `2.3.3`
* `coroutines`: `1.7.3`
* `koin`: `3.4.3`
## 7.0.0
* `Version`:
* `microutils`: `0.19.7`
* `tgbotapi`: `9.0.0`
* `ktor`: `2.3.2`
* `coroutines`: `1.7.2`
## 6.1.0
* `Version`:
* `kotlin`: `1.8.22`
* `microutils`: `0.19.4`
* `tgbotapi`: `8.1.0`
* `koin`: `3.4.2`
* `sqlite`: `3.42.0.0`
## 6.0.1
* `Version`:
* `microutils`: `0.19.2`
* `tgbotapi`: `8.0.1`
* `uuid`: `0.7.1`
* `ktor`: `2.3.1`
* `koin`: `3.4.1`
## 6.0.0
* `Versions`:
* `microutils`: `0.19.1`
* `tgbotapi`: `8.0.0`
* `klock`: `4.0.3`
## 5.1.3
* `Versions`:
* `serialization`: `1.5.1`
* `microutils`: `0.18.4`
* `tgbotapi`: `7.1.3`
## 5.1.2
* `Versions`:
* `microutils`: `0.18.1`
* `tgbotapi`: `7.1.2`
## 5.1.1
* `Versions`:
* `kotlin`: `1.8.21`
* `microutils`: `0.18.0`
* `tgbotapi`: `7.1.1`
## 5.1.0
* `Versions`:
* `tgbotapi`: `7.1.0`
* `sqlite`: `3.41.2.1`
## 5.0.2
* `Versions`:
* `kotlin`: `1.8.20`
* `microutils`: `0.17.8`
* `tgbotapi`: `7.0.2`
* `kslog`: `1.1.1`
* `ktor`: `2.3.0`
* `koin`: `3.4.0`
## 5.0.1
* `Versions`:
* `tgbotapi`: `7.0.1`
## 5.0.0
* `Versions`:
* `tgbotapi`: `7.0.0`
* `microutils`: `0.17.5`
## 4.1.0
* `Versions`:
* `tgbotapi`: `6.1.0`
* `microutils`: `0.17.3`
## 4.0.3
* `Versions`:
* `tgbotapi`: `6.0.3`
* `microutils`: `0.17.2`
## 4.0.2
* `Versions`:
* `tgbotapi`: `6.0.2`
## 4.0.1
* `Versions`:
* `tgbotapi`: `6.0.1`
* `microutils`: `17.0.1`
* `ktor`: `2.2.4`
## 4.0.0
* `Versions`:
* `kotlin`: `1.8.10`
* `tgbotapi`: `6.0.0`
* `microutils`: `0.17.0`
## 3.5.0
* `Versions`:
* `tgbotapi`: `5.2.0`
* `microutils`: `0.16.10`
* `koin`: `3.3.2`
## 3.4.1
* `setupBotPlugin` now works synchronously
## 3.4.0
* `Versions`:
* `tgbotapi`: `5.1.0`
* `microutils`: `0.16.8`
* `ktor`: `2.2.3`
## 3.3.1
* `Versions`:
* `tgbotapi`: `5.0.1`
* `microutils`: `0.16.6`
* `ktor`: `2.2.2`
## 3.3.0
* `Versions`:
* `tgbotapi`: `5.0.0`
## 3.2.3
* `Versions`:
* `tgbotapi`: `4.2.3`
* `microutils`: `0.16.4`
## 3.2.2
* `Versions`:
* `tgbotapi`: `4.2.2`
* `microutils`: `0.16.2`
## 3.2.1
* `Versions`:
* `tgbotapi`: `4.2.1`
* `microutils`: `0.16.0`
* `ktor`: `2.2.1`
## 3.2.0
* `Versions`:
* `kotlin`: `1.7.22`
* `tgbotapi`: `4.2.0`
* `microutils`: `0.15.0`
* `kslog`: `0.5.4`
* `sqlite`: `3.40.0.0`
## 3.1.4
* `Versions`:
* `tgbotapi`: `4.1.3`
* `microutils`: `0.14.4`
## 3.1.3
* `Versions`:
* `tgbotapi`: `4.1.2`
## 3.1.2
* `Versions`:
* `microutils`: `0.14.2`
* `exposed`: `0.41.1`
## 3.1.1
* `Versions`:
* `tgbotapi`: `4.1.1`
## 3.1.0
* `Versions`:
* `kotlin`: `1.7.21`
* `microutils`: `0.14.1`
* `tgbotapi`: `4.1.0`
* `klock`: `3.4.0`
* `uuid`: `0.6.0`
## 3.0.0
* `Versions`:
* `microutils`: `0.14.0`
* `tgbotapi`: `4.0.0`
* `kslog`: `0.5.3`
* `exposed`: `0.40.1`
* `klock`: `3.3.1`
## 2.4.1
* `Versions`:
* `microutils`: `0.13.2`
* `tgbotapi`: `3.3.1`
* `klock`: `3.3.0`
* `ktor`: `2.1.3`
* `koin`: `3.2.2`
## 2.4.0
* `Versions`:
* `kotlin`: `1.7.20`
* `serialization`: `1.4.1`
* `tgbotapi`: `3.3.0`
* `microutils`: `0.13.1`
* `klock`: `3.2.0`
* `ktor`: `2.1.2`
## 2.3.4
* `Versions`:
* `tgbotapi`: `3.2.7`
* `microutils`: `0.12.16`
## 2.3.3
* `Versions`:
* `tgbotapi`: `3.2.6`
* `sqlite`: `3.39.3.0`
## 2.3.2
* `Versions`:
* `tgbotapi`: `3.2.3`
* `microutils`: `0.12.13`
* `kslog`: `0.5.2`
## 2.3.1
* `Versions`:
* `klock`: `3.1.0`
* `tgbotapi`: `3.2.1`
* `microutils`: `0.12.11`
* `ktor`: `2.1.1`
## 2.3.0
* `Bot`:
* Add option `reconnectOptions` in database config
## 2.2.0
* `Versions`:
* `serialization`: `1.4.0`
* `tgbotapi`: `3.2.0`
* `microutils`: `0.12.4`
* `kslog`: `0.5.1`
## 2.1.1
* `Bot`:
* Now it is possible to get bot from `koin`
## 2.1.0
* `Versions`:
* `tgbotapi`: `3.1.1`
* `ktor`: `2.1.0`
* `microutils`: `0.12.1`
* `Plugins`:
* New fum of `Plugin` with `BehaviourContextWithFSM` receiver
* `Bot`:
* Now bot uses `buildBehaviourWithFSM` to be able to setup bot with FSM
## 2.0.0
* `Versions`:
* `kotlin`: `1.7.10`
* `serialization`: `1.4.0-RC`
* `tgbotapi`: `3.0.2`
* `kslog`: `0.5.0`
* `uuid`: `0.5.0`
* `exposed`: `0.39.2`
* `microutils`: `0.12.0`
## 1.4.1
* `Versions`:
* `tgbotapi`: `2.2.2`
* `kslog`: `0.4.2`
## 1.4.0
* `Versions`:
* `kslog`: `0.4.1`
## 1.3.1
* `Versions`:
* `tgbotapi`: `2.2.1`
* `microutils`: `0.11.13`
## 1.3.0
* `Versions`
* `tgbotapi`: `2.2.0`
## 1.2.3
* `Versions`
* `tgbotapi`: `2.1.3`
## 1.2.2
* `Versions`
* `tgbotapi`: `2.1.2`
* `microutils`: `0.11.12`
* `coroutines`: `1.6.3`
* `ktor`: `2.0.3`
## 1.2.1
* `Versions`
* `tgbotapi`: `2.1.1`
* `microutils`: `0.11.6`
* `kslog`: `0.3.2`
## 1.2.0
* `Versions`
* `tgbotapi`: `2.1.0`
## 1.1.2
* `Versions`
* `tgbotapi`: `2.0.3`
* `microutils`: `0.11.3`
* `kslog`: `0.3.1`
* `Plugin`:
* Now it is possible to use `object`s of plugins instead of classes
## 1.1.1
* `Versions`
* `coroutines`: `1.6.2`
* `tgbotapi`: `2.0.2`
* `microutils`: `0.11.0`
* `ktor`: `2.0.2`
* `uuid`: `0.4.1`
## 1.1.0
* `Versions`
* `tgbotapi`: `2.0.0`
* `microutils`: `0.10.5`
* `Plugin`:
* All plugins will be loaded in parallel
## 1.0.0
* `Versions`
* `kotlin`: `1.6.21`
* `coroutines`: `1.6.1`
* `serialization`: `1.3.3`
* `exposed`: `0.38.2`
* `tgbotapi`: `1.1.0`
* `microutils`: `0.10.4`
* `Common`:
* ___ALL THE SDI/KLASSINDEX FUNCTIONALITY HAS BEEN REMOVED___
* `Plugin`:
* Now plugins must have empty constructor
* Now plugins may provide realization of two methods: `setupDI` and `setupBotPlugin`
* `PlaguBot`:
* `Config` now is simple serializable `data class`
* `PlaguBot` now is more simple as a plugin
## 0.5.1
* `Versions`

View File

@@ -16,3 +16,43 @@ You can create your bot using
That is a set of libraries for plagubots. Look at the
[PlaguBot Plugin template](https://insanusmokrassar.github.io/PlaguBotPluginTemplate/) to find how to create your bot.
### Technical help
#### FSM
In this bot has been used variant with FSM. That means that you may use all the [Behaviour Builder with FSM](https://bookstack.inmo.dev/books/telegrambotapi/page/behaviour-builder-with-fsm) functionality. In case you wish to setup states repo, you should use the next code in the `setupDI` of your plugin:
```kotlin
single<StatesManager<State>> {
// setup your manager and return here
// Default is:
DefaultStatesManager(
InMemoryDefaultStatesManagerRepo()
)
}
```
Besides, you may setup handling errors lambda in the same function:
```kotlin
single<StateHandlingErrorHandler<State>> {
{ state, e ->
logger.eS(e) { "Unable to handle state $state" } // logging by default
null // you should return new state or null, default callback will return null
}
}
```
#### Subcontext initial actions
Bot will take all the `CombinedSubcontextInitialAction.SubItem`s from `Koin` to include it in root of
`behaviourBuilder`. To create your own subitem:
```kotlin
singleWithRandomQualifier<CombinedSubcontextInitialAction.SubItem> {
CombinedSubcontextInitialAction.SubItem {
// do some action or throw error to rerun on next round
}
}
```

View File

@@ -1,8 +1,8 @@
plugins {
id 'org.jetbrains.kotlin.jvm'
id "org.jetbrains.kotlin.plugin.serialization"
id "org.jetbrains.kotlin.kapt"
id 'application'
id "com.google.devtools.ksp"
}
project.group="$group"
@@ -11,21 +11,20 @@ project.version="$version"
apply from: "publish.gradle"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
api "org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlin_serialisation_runtime_version"
api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
api "org.jetbrains.exposed:exposed-jdbc:$kotlin_exposed_version"
implementation libs.kt.stdlib
api libs.kt.coroutines
api libs.kt.serialization
api libs.jb.exposed.jdbc
api "dev.inmo:tgbotapi:$tgbotapi_version"
api "dev.inmo:sdi:$sdi_version"
api "dev.inmo:micro_utils.repos.exposed:$microutils_version"
api libs.tgbotapi
api libs.tgbotapi.behaviourBuilder.fsm
api libs.microutils.repos.exposed
api libs.microutils.koin
api libs.microutils.startup.launcher
api "com.github.matfax.klassindex:library:$klassindex_version"
kapt "com.github.matfax.klassindex:processor:$klassindex_version"
api "org.xerial:sqlite-jdbc:$sqlite_version"
api libs.sqlite
testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
testImplementation libs.kt.test.junit
api project(":plagubot.plugin")
}
@@ -34,15 +33,11 @@ application {
mainClassName = 'dev.inmo.plagubot.AppKt'
}
kapt {
arguments {
arg("com.github.matfax.klassindex.IndexSubclasses", "dev.inmo.plagubot.Plugin")
arg("com.github.matfax.klassindex.IndexAnnotated", "dev.inmo.sdi.SDIIncluded")
}
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
ksp { // this generator do not require any arguments and we should left `ksp` empty
}

View File

@@ -1 +0,0 @@
{"bintrayConfig":{"repo":"PlaguBot","packageName":"${project.name}","packageVcs":"https://github.com/InsanusMokrassar/PlaguBot","autoPublish":true,"overridePublish":true},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/PlaguBot/LICENSE"}],"mavenConfig":{"name":"PlaguBot Bot","description":"Base PlaguBot project","url":"https://github.com/InsanusMokrassar/PlaguBot","vcsUrl":"ssh://git@github.com/InsanusMokrassar/PlaguBot.git","includeGpgSigning":true,"publishToMavenCentral":true,"developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"}]},"type":"JVM"}

View File

@@ -1,14 +1,14 @@
apply plugin: 'maven-publish'
apply plugin: 'signing'
task javadocJar(type: Jar) {
from javadoc
classifier = 'javadoc'
archiveClassifier = 'javadoc'
}
task sourcesJar(type: Jar) {
from sourceSets.main.allSource
classifier = 'sources'
archiveClassifier = 'sources'
}
publishing {
@@ -50,33 +50,69 @@ publishing {
}
}
repositories {
maven {
name = "bintray"
url = uri("https://api.bintray.com/maven/${project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')}/PlaguBot/${project.name}/;publish=1;override=1")
credentials {
username = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')
password = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
}
}
maven {
name = "sonatype"
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
}
}
}
repositories {
if ((project.hasProperty('INMONEXUS_USER') || System.getenv('INMONEXUS_USER') != null) && (project.hasProperty('INMONEXUS_PASSWORD') || System.getenv('INMONEXUS_PASSWORD') != null)) {
maven {
name = "InmoNexus"
url = uri("https://nexus.inmo.dev/repository/maven-releases/")
credentials {
username = project.hasProperty('INMONEXUS_USER') ? project.property('INMONEXUS_USER') : System.getenv('INMONEXUS_USER')
password = project.hasProperty('INMONEXUS_PASSWORD') ? project.property('INMONEXUS_PASSWORD') : System.getenv('INMONEXUS_PASSWORD')
}
}
}
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
maven {
name = "sonatype"
url = uri("https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/")
credentials {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
}
}
}
}
signing {
useGpgCmd()
sign publishing.publications
if (project.hasProperty("signing.gnupg.keyName")) {
apply plugin: 'signing'
signing {
useGpgCmd()
sign publishing.publications
}
task signAll {
tasks.withType(Sign).forEach {
dependsOn(it)
}
}
// Workaround to make android sign operations depend on signing tasks
project.getTasks().withType(AbstractPublishToMaven.class).configureEach {
def signingTasks = project.getTasks().withType(Sign.class)
mustRunAfter(signingTasks)
}
// Workaround to make test tasks use sign
project.getTasks().withType(Sign.class).configureEach { signTask ->
def withoutSign = (signTask.name.startsWith("sign") ? signTask.name.minus("sign") : signTask.name)
def pubName = withoutSign.endsWith("Publication") ? withoutSign.substring(0, withoutSign.length() - "Publication".length()) : withoutSign
// These tasks only exist for native targets, hence findByName() to avoid trying to find them for other targets
// Task ':linkDebugTest<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
def debugTestTask = tasks.findByName("linkDebugTest$pubName")
if (debugTestTask != null) {
signTask.mustRunAfter(debugTestTask)
}
// Task ':compileTestKotlin<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
def testTask = tasks.findByName("compileTestKotlin$pubName")
if (testTask != null) {
signTask.mustRunAfter(testTask)
}
}
}

1
bot/publish.kpsb Normal file
View File

@@ -0,0 +1 @@
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/PlaguBot/LICENSE"}],"mavenConfig":{"name":"PlaguBot Bot","description":"Base PlaguBot project","url":"https://github.com/InsanusMokrassar/PlaguBot","vcsUrl":"ssh://git@github.com/InsanusMokrassar/PlaguBot.git","developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"InmoNexus","url":"https://nexus.inmo.dev/repository/maven-releases/"},{"name":"sonatype","url":"https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}},"type":"JVM"}

View File

@@ -1,18 +1,11 @@
package dev.inmo.plagubot
import dev.inmo.plagubot.config.*
import kotlinx.coroutines.*
import kotlinx.serialization.InternalSerializationApi
import java.io.File
/**
* This method by default expects one argument in [args] field: path to config
*/
@InternalSerializationApi
suspend fun main(args: Array<String>) {
val (configPath) = args
val file = File(configPath)
val config = configAndPluginsConfigJsonFormat.decodeFromString(PluginsConfigurationSerializer, file.readText()) as Config
PlaguBot(config).start().join()
PlaguBot.start(args).join()
}

View File

@@ -1,16 +0,0 @@
package dev.inmo.plagubot
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.jetbrains.exposed.sql.Database
@Serializable
@SerialName("Hello")
data class HelloPlugin(
val parameter: String
) : Plugin {
override suspend fun BehaviourContext.invoke(database: Database) {
println(parameter)
}
}

View File

@@ -0,0 +1,28 @@
package dev.inmo.plagubot
import org.koin.core.Koin
import org.koin.core.definition.Definition
import org.koin.core.module.Module
import org.koin.core.qualifier.Qualifier
import org.koin.core.qualifier.StringQualifier
import org.koin.core.scope.Scope
val Scope.plagubot: PlaguBot
get() = get()
val Koin.plagubot: PlaguBot
get() = get()
private val pluginsQualifier = StringQualifier("plagubotPlugins")
internal fun Module.singlePlugins(
createdAtStart: Boolean = false,
definition: Definition<List<Plugin>>
) = single(pluginsQualifier, createdAtStart, definition)
val Scope.plugins: List<Plugin>
get() = get(pluginsQualifier)
val Koin.plugins: List<Plugin>
get() = get(pluginsQualifier)

View File

@@ -0,0 +1,16 @@
package dev.inmo.plagubot
import dev.inmo.micro_utils.fsm.common.State
fun interface OnStartContextsConflictResolver {
/**
* @param old Old state which is currently placed on the [State.context]
* @param new New state pretend to replace [old] one
* @return Should return:
*
* * Null in case when current realization unable to resolve conflict
* * False when current realization knows that [new] [State] must **not** replace [old] one
* * True when current realization knows that [new] [State] must replace [old] one
*/
suspend operator fun invoke(old: State, new: State): Boolean?
}

View File

@@ -0,0 +1,20 @@
package dev.inmo.plagubot
import dev.inmo.micro_utils.fsm.common.State
fun interface OnUpdateContextsConflictResolver {
/**
* This method will be called when [sourceStateWithOldContext] [State.context] and [newStateWithNewContext] are not equal and currently there is
* launched [currentStateOnNewContext] state on the chain with [State.context] from [currentStateOnNewContext]
*
* @param sourceStateWithOldContext Old state where from [newStateWithNewContext] came
* @param newStateWithNewContext New state with changing [State.context] (it is different with [sourceStateWithOldContext] [State.context])
* @param currentStateOnNewContext State which is currently running on [newStateWithNewContext] [State.context]
* @return Should return:
*
* * Null in case when current realization unable to resolve conflict
* * False when [currentStateOnNewContext] **should not** be stopped in favor to [newStateWithNewContext]
* * True when [currentStateOnNewContext] **should** be stopped in favor to [newStateWithNewContext]
*/
suspend operator fun invoke(sourceStateWithOldContext: State, newStateWithNewContext: State, currentStateOnNewContext: State): Boolean?
}

View File

@@ -1,55 +1,167 @@
package dev.inmo.plagubot
import dev.inmo.micro_utils.coroutines.safelyWithoutExceptions
import dev.inmo.kslog.common.*
import dev.inmo.micro_utils.common.Warning
import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.micro_utils.fsm.common.State
import dev.inmo.micro_utils.fsm.common.StatesManager
import dev.inmo.micro_utils.fsm.common.managers.*
import dev.inmo.micro_utils.koin.getAllDistinct
import dev.inmo.micro_utils.pagination.utils.getAll
import dev.inmo.micro_utils.startup.launcher.StartLauncherPlugin
import dev.inmo.plagubot.config.*
import dev.inmo.tgbotapi.bot.Ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.bot.ktor.KtorRequestsExecutorBuilder
import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.webhook.deleteWebhook
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.types.botCommandsLimit
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
import kotlinx.coroutines.*
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import org.jetbrains.exposed.sql.Database
const val DefaultPlaguBotParamsKey = "plagubot"
val Map<String, Any>.plagubot
get() = get(DefaultPlaguBotParamsKey) as? PlaguBot
import kotlinx.serialization.json.*
import org.koin.core.Koin
import org.koin.core.module.Module
import org.koin.core.scope.Scope
import java.io.File
@OptIn(Warning::class)
@Serializable
data class PlaguBot(
@Serializable(PluginsConfigurationSerializer::class)
private val config: Config
) : Plugin {
@Transient
private val bot = telegramBot(config.botToken)
@Transient
private val paramsMap = config.params ?.toMap() ?: emptyMap()
@Transient
private val database = config.params ?.database ?: config.database.database
override suspend fun getCommands(): List<BotCommand> = config.plugins.flatMap {
it.getCommands()
object PlaguBot : Plugin {
override fun KtorRequestsExecutorBuilder.setupBotClient(scope: Scope, params: JsonObject) {
scope.plugins.filter { it !== this@PlaguBot }.forEach {
with(it) {
setupBotClient(scope, params)
}
}
}
override suspend fun BehaviourContext.invoke(database: Database, params: Map<String, Any>) {
config.plugins.forEach {
it.apply { invoke(database, params) }
override fun Module.setupDI(config: JsonObject) {
single { get<Json>().decodeFromJsonElement(Config.serializer(), config) }
single { config }
single { get<Config>().databaseConfig }
single { get<Config>().databaseConfig.database }
single { this@PlaguBot }
singlePlugins { get<dev.inmo.micro_utils.startup.launcher.Config>().plugins.filterIsInstance<Plugin>() }
single {
val config = get<Config>()
telegramBot(
token = config.botToken,
testServer = config.testServer,
apiUrl = config.botApiServer
) {
setupBotClient(this@single, get<JsonObject>())
}
}
val commands = getCommands()
val futureUnavailable = commands.drop(botCommandsLimit.last)
if (futureUnavailable.isNotEmpty()) {
println("Next commands are out of range in setting command request and will be unavailable from autocompleting: $futureUnavailable")
}
safelyWithoutExceptions { setMyCommands(commands.take(botCommandsLimit.last)) }
}
/**
* This method will create an [Job] which will be the main [Job] of ran instance
* Getting all [OnStartContextsConflictResolver], [OnUpdateContextsConflictResolver], [StatesManager] and [DefaultStatesManagerRepo]
* and pass them into [buildBehaviourWithFSM] on top of [TelegramBot] took from [koin]. In time of
* [buildBehaviourWithFSM] configuration will call [setupBotPlugin] and [deleteWebhook].
*
* After all preparation, the result of [buildBehaviourWithFSM] will be passed to [startGettingOfUpdatesByLongPolling]
* as [CoroutineScope] and [UpdatesFilter].
*
* The [Job] took from [startGettingOfUpdatesByLongPolling] will be used to prevent app stopping by calling [Job.join]
* on it
*/
suspend fun start(
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
): Job = bot.buildBehaviourWithLongPolling(scope) {
invoke(database, paramsMap)
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
val scope = koin.get<CoroutineScope>()
lateinit var behaviourContext: BehaviourContext
val onStartContextsConflictResolver by lazy { koin.getAllDistinct<OnStartContextsConflictResolver>() }
val onUpdateContextsConflictResolver by lazy { koin.getAllDistinct<OnUpdateContextsConflictResolver>() }
val bot = koin.get<TelegramBot>()
bot.buildBehaviourWithFSM(
scope = scope,
defaultExceptionsHandler = {
logger.e("Something went wrong", it)
},
statesManager = koin.getOrNull<StatesManager<State>>() ?: DefaultStatesManager(
koin.getOrNull<DefaultStatesManagerRepo<State>>() ?: InMemoryDefaultStatesManagerRepo<State>(),
onStartContextsConflictResolver = { old, new -> onStartContextsConflictResolver.firstNotNullOfOrNull { it(old, new) } ?: false },
onUpdateContextsConflictResolver = { old, new, currentNew -> onUpdateContextsConflictResolver.firstNotNullOfOrNull { it(old, new, currentNew) } ?: false }
),
onStateHandlingErrorHandler = koin.getOrNull<StateHandlingErrorHandler<State>>() ?: { state, e ->
logger.eS(e) { "Unable to handle state $state" }
null
},
subcontextInitialAction = CombinedSubcontextInitialAction(koin.getAllDistinct()).subcontextInitialAction
) {
logger.i("Start setup of bot part")
behaviourContext = this
setupBotPlugin(koin)
deleteWebhook()
}.start()
logger.i("Behaviour builder has been setup")
bot.startGettingOfUpdatesByLongPolling(scope = behaviourContext, updatesFilter = behaviourContext).also {
logger.i("Long polling has been started")
}.join()
}
/**
* Initializing [Plugin]s from [koin] took by [plugins] extension. [PlaguBot] itself will be filtered out from
* list of plugins to be inited
*/
override suspend fun BehaviourContextWithFSM<State>.setupBotPlugin(koin: Koin) {
koin.plugins.filter { it !== this@PlaguBot }.forEach { plugin ->
runCatchingSafely {
logger.i("Start loading of $plugin")
with(plugin) {
setupBotPlugin(koin)
}
}.onFailure { e ->
logger.w("Unable to load bot part of $plugin", e)
}.onSuccess {
logger.i("Complete loading of $plugin")
}
}
}
/**
* Starting plugins system using [StartLauncherPlugin.start]. In time of parsing [initialJson] [PlaguBot] may
* add itself in its `plugins` section in case of its absence there. So, by launching this [start] it is guaranteed
* that [PlaguBot] will be in list of plugins to be loaded by [StartLauncherPlugin]
*/
suspend fun start(initialJson: JsonObject): Job {
val initialConfig = defaultJsonFormat.decodeFromJsonElement(dev.inmo.micro_utils.startup.launcher.Config.serializer(), initialJson)
KSLog.i("Config has been read")
// Adding of PlaguBot when it absent in config
val (resultJson, resultConfig) = if (PlaguBot in initialConfig.plugins) {
KSLog.i("Initial config contains PlaguBot, pass config as is to StartLauncherPlugin")
initialJson to initialConfig
} else {
KSLog.i("Start fixing of PlaguBot absence. If PlaguBot has been skipped by some reason, use dev.inmo.micro_utils.startup.launcher.main as startup point or StartLauncherPlugin directly")
val resultJson = JsonObject(
initialJson + Pair("plugins", JsonArray(initialJson["plugins"]!!.jsonArray + JsonPrimitive(PlaguBot::class.qualifiedName!!)))
)
val resultConfig = defaultJsonFormat.decodeFromJsonElement(dev.inmo.micro_utils.startup.launcher.Config.serializer(), resultJson)
resultJson to resultConfig
}
KSLog.i("Config initialization done. Passing config to StartLauncherPlugin")
return StartLauncherPlugin.start(
resultConfig,
resultJson
).koin.get<CoroutineScope>().coroutineContext.job
}
/**
* Accepts single argument in [args] which will be interpreted as [File] path with [StartLauncherPlugin]
* configuration content. After reading of that file as [JsonObject] will pass it in [start] with [JsonObject] as
* argument
*/
suspend fun start(args: Array<String>): Job {
KSLog.default = KSLog("PlaguBot")
val (configPath) = args
val file = File(configPath)
KSLog.i("Start read config from ${file.absolutePath}")
val initialJson = defaultJsonFormat.parseToJsonElement(file.readText()).jsonObject
return start(initialJson)
}
}

View File

@@ -1,25 +0,0 @@
package dev.inmo.plagubot
import dev.inmo.plagubot.config.PluginsConfigurationSerializer
import dev.inmo.plagubot.config.SimplePluginsConfiguration
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.types.BotCommand
import kotlinx.serialization.Serializable
import org.jetbrains.exposed.sql.Database
@Serializable
data class PluginsHolder(
@Serializable(PluginsConfigurationSerializer::class)
private val pluginsConfiguration: SimplePluginsConfiguration
) : Plugin {
override suspend fun getCommands(): List<BotCommand> = pluginsConfiguration.plugins.flatMap {
it.getCommands()
}
override suspend fun BehaviourContext.invoke(database: Database, params: Map<String, Any>) {
val finalParams = pluginsConfiguration.params ?.plus(params) ?: params
pluginsConfiguration.plugins.forEach {
it.apply { invoke(database, finalParams) }
}
}
}

View File

@@ -1,15 +1,18 @@
package dev.inmo.plagubot.config
import dev.inmo.micro_utils.common.Warning
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import dev.inmo.plagubot.Plugin
import dev.inmo.sdi.Module
import kotlinx.serialization.Contextual
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Warning("This API is internal and can be changed without notifications or mentions of changes")
@Serializable
data class Config(
override val plugins: List<@Contextual Plugin>,
val database: DatabaseConfig = DatabaseConfig(),
val botToken: String,
@Contextual
override val params: Module? = null
) : PluginsConfiguration
@SerialName("database")
val databaseConfig: DatabaseConfig = DatabaseConfig(),
val botApiServer: String = telegramBotAPIDefaultUrl,
val testServer: Boolean = false
)

View File

@@ -0,0 +1,9 @@
package dev.inmo.plagubot.config
import kotlinx.serialization.Serializable
@Serializable
data class DBConnectOptions(
val attempts: Int = 3,
val delay: Long = 1000L
)

View File

@@ -1,32 +1,43 @@
package dev.inmo.plagubot.config
import dev.inmo.sdi.SDIIncluded
import dev.inmo.kslog.common.e
import dev.inmo.kslog.common.logger
import kotlinx.coroutines.delay
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.transactions.transactionManager
import org.koin.core.scope.Scope
import org.sqlite.JDBC
import java.lang.Exception
import java.sql.Connection
const val defaultDatabaseParamsName = "defaultDatabase"
inline val Map<String, Any>.database: Database?
get() = (get(defaultDatabaseParamsName) as? DatabaseConfig) ?.database
inline val Scope.database: Database?
get() = getOrNull<Database>()
@Serializable
@SDIIncluded
data class DatabaseConfig(
val url: String = "jdbc:sqlite:file:test?mode=memory&cache=shared",
val driver: String = JDBC::class.qualifiedName!!,
val username: String = "",
val password: String = ""
val password: String = "",
val reconnectOptions: DBConnectOptions? = DBConnectOptions()
) {
@Transient
val database: Database = Database.connect(
url,
driver,
username,
password
).also {
it.transactionManager.defaultIsolationLevel = Connection.TRANSACTION_SERIALIZABLE // Or Connection.TRANSACTION_READ_UNCOMMITTED
}
val database: Database = (0 until (reconnectOptions ?.attempts ?: 1)).firstNotNullOfOrNull {
runCatching {
Database.connect(
url,
driver,
username,
password
).also {
it.transactionManager.defaultIsolationLevel = Connection.TRANSACTION_SERIALIZABLE // Or Connection.TRANSACTION_READ_UNCOMMITTED
it.connector().close()
}
}.onFailure {
logger.e(it)
Thread.sleep(reconnectOptions ?.delay ?: return@onFailure)
}.getOrNull()
} ?: error("Unable to create database")
}

View File

@@ -0,0 +1,9 @@
package dev.inmo.plagubot.config
import dev.inmo.micro_utils.common.Warning
import kotlinx.serialization.json.Json
@Warning("This format will not be configured throw StartPlugin system. Use it will caution, it has no any configured things")
val defaultJsonFormat = Json {
ignoreUnknownKeys = true
}

View File

@@ -1,190 +0,0 @@
package dev.inmo.plagubot.config
import com.github.matfax.klassindex.KlassIndex
import dev.inmo.plagubot.Plugin
import dev.inmo.plagubot.PluginSerializer
import dev.inmo.sdi.Module
import dev.inmo.sdi.ModuleSerializer
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*
import kotlinx.serialization.modules.*
import kotlin.reflect.KClass
@InternalSerializationApi
internal inline fun <T : Plugin> KClass<T>.includeIn(builder: PolymorphicModuleBuilder<Plugin>) = builder.subclass(this, serializer())
@InternalSerializationApi
internal val configAndPluginsConfigJsonFormat: Json
get() = Json {
ignoreUnknownKeys = true
serializersModule = SerializersModule {
polymorphic(Plugin::class) {
KlassIndex.getSubclasses(Plugin::class).flatMap { kclass ->
kclass.includeIn(this)
kclass.annotations.mapNotNull { it as? SerialName }.map {
it.value to kclass.serializer()
} + listOfNotNull(
kclass.simpleName ?.let {
it to kclass.serializer()
}
)
}.toMap().let {
default { requiredType ->
it[requiredType]
}
}
}
}
}
internal interface PluginsConfiguration {
val plugins: List<Plugin>
val params: Module?
}
@Serializable
data class SimplePluginsConfiguration(
override val plugins: List<@Contextual Plugin>,
@Contextual
override val params: Module? = null
) : PluginsConfiguration
internal val DefaultModuleSerializer = ModuleSerializer(emptyList()) {
}
@Serializer(Plugin::class)
internal class InternalPluginSerializer(
private val params: Module
) : KSerializer<Plugin> {
override val descriptor: SerialDescriptor = PluginSerializer.descriptor
@OptIn(InternalSerializationApi::class)
override fun deserialize(decoder: Decoder): Plugin {
val asJson = JsonElement.serializer().deserialize(decoder)
return if (asJson is JsonPrimitive) {
params[asJson.jsonPrimitive.content] as Plugin
} else {
val jsonFormat = ((decoder as? JsonDecoder)?.json ?: configAndPluginsConfigJsonFormat)
jsonFormat.decodeFromJsonElement(PluginSerializer, asJson)
}
}
@OptIn(InternalSerializationApi::class)
override fun serialize(encoder: Encoder, value: Plugin) {
params.keys.firstOrNull { params[it] === value } ?.also {
encoder.encodeString(it)
} ?: PluginSerializer.serialize(encoder, value)
}
}
@Serializer(Module::class)
internal class InternalModuleSerializer(
private val original: JsonElement?,
private val params: Module
) : KSerializer<Module> {
override val descriptor: SerialDescriptor = PluginSerializer.descriptor
@OptIn(InternalSerializationApi::class)
override fun deserialize(decoder: Decoder): Module {
val asJson = JsonElement.serializer().deserialize(decoder)
return if (asJson == original) {
params
} else {
configAndPluginsConfigJsonFormat.decodeFromJsonElement(DefaultModuleSerializer, asJson)
}
}
@OptIn(InternalSerializationApi::class)
override fun serialize(encoder: Encoder, value: Module) = DefaultModuleSerializer.serialize(encoder, value)
}
internal fun internalPluginSerializerSerializersModule(
internalPluginSerializer: InternalPluginSerializer,
internalModuleSerializer: InternalModuleSerializer?
) = SerializersModule {
contextual(internalPluginSerializer)
contextual(internalModuleSerializer ?: return@SerializersModule)
}
@Serializer(PluginsConfiguration::class)
internal object PluginsConfigurationSerializer : KSerializer<PluginsConfiguration> {
private val jsonSerializer = JsonObject.serializer()
private val moduleSerializer = ModuleSerializer()
override val descriptor: SerialDescriptor = jsonSerializer.descriptor
@OptIn(InternalSerializationApi::class)
override fun deserialize(decoder: Decoder): PluginsConfiguration {
val json = jsonSerializer.deserialize(decoder)
val jsonFormat = (decoder as? JsonDecoder) ?.json ?: configAndPluginsConfigJsonFormat
val paramsRow = json["params"]
val resultJsonFormat = if (paramsRow != null && paramsRow != JsonNull) {
val params = jsonFormat.decodeFromJsonElement(
moduleSerializer,
paramsRow
)
val pluginsSerializer = InternalPluginSerializer(params)
val moduleSerializer = InternalModuleSerializer(paramsRow, params)
Json(jsonFormat) {
serializersModule = decoder.serializersModule.overwriteWith(
internalPluginSerializerSerializersModule(pluginsSerializer, moduleSerializer)
)
}
} else {
jsonFormat
}
return try {
resultJsonFormat.decodeFromJsonElement(
Config.serializer(),
json
)
} catch (e: SerializationException) {
resultJsonFormat.decodeFromJsonElement(
SimplePluginsConfiguration.serializer(),
json
)
}
}
@OptIn(InternalSerializationApi::class)
override fun serialize(encoder: Encoder, value: PluginsConfiguration) {
val params = value.params
val serializer = when (value) {
is Config -> Config.serializer()
is SimplePluginsConfiguration -> SimplePluginsConfiguration.serializer()
else -> return
}
if (params != null) {
val pluginsSerializer = InternalPluginSerializer(params)
val jsonFormat = Json(configAndPluginsConfigJsonFormat) {
serializersModule = encoder.serializersModule.overwriteWith(
internalPluginSerializerSerializersModule(pluginsSerializer, null)
)
}
jsonSerializer.serialize(
encoder,
when (value) {
is Config -> jsonFormat.encodeToJsonElement(Config.serializer(), value)
is SimplePluginsConfiguration -> jsonFormat.encodeToJsonElement(SimplePluginsConfiguration.serializer(), value)
else -> return
} as JsonObject
)
} else {
when (value) {
is Config -> Config.serializer().serialize(encoder, value)
is SimplePluginsConfiguration -> SimplePluginsConfiguration.serializer().serialize(encoder, value)
else -> return
}
}
}
}

View File

@@ -0,0 +1,3 @@
package dev.inmo.plagubot.config
typealias StateHandlingErrorHandler<T> = suspend (T, Throwable) -> T?

View File

@@ -1,40 +0,0 @@
package dev.inmo.plagubot.config
import dev.inmo.plagubot.HelloPlugin
import kotlinx.serialization.InternalSerializationApi
import org.junit.Test
import kotlin.test.assertEquals
class ConfigTest {
@InternalSerializationApi
@Test
fun testThatPluginPassedToParamsWillBeCorrectlyUsedInPlugins() {
val rawConfig = """
{
"database": {
},
"botToken": "",
"plugins": [
"helloPlugin"
],
"params": {
"helloPlugin": {"type": "dev.inmo.plagubot.HelloPlugin", "parameter": "Example"}
}
}
""".trimIndent()
val config = configAndPluginsConfigJsonFormat.decodeFromString(PluginsConfigurationSerializer, rawConfig) as Config
assert(config.plugins.size == 1)
assert(config.plugins.first() is HelloPlugin)
assert((config.plugins.first() as HelloPlugin).parameter == "Example")
val redecoded = configAndPluginsConfigJsonFormat.decodeFromString(
PluginsConfigurationSerializer,
configAndPluginsConfigJsonFormat.encodeToString(PluginsConfigurationSerializer, config)
) as Config
assertEquals(config.database, redecoded.database)
assertEquals(config.plugins, redecoded.plugins)
assertEquals(config.botToken, redecoded.botToken)
assertEquals(config.params ?.toMap(), redecoded.params ?.toMap())
}
}

View File

@@ -1,22 +1,41 @@
buildscript {
repositories {
jcenter()
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.github.breadmoirai:github-release:$github_release_plugin_version"
classpath libs.buildscript.kt.gradle
classpath libs.buildscript.kt.serialization
classpath libs.buildscript.gh.release
classpath libs.buildscript.ksp
}
}
plugins {
alias(libs.plugins.nmcp.aggregation)
}
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
nmcpAggregation {
centralPortal {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
validationTimeout = Duration.ofHours(4)
publishingType = System.getenv('PUBLISHING_TYPE') != "" ? System.getenv('PUBLISHING_TYPE') : "USER_MANAGED"
}
publishAllProjectsProbablyBreakingProjectIsolation()
}
}
allprojects {
repositories {
mavenCentral()
jcenter()
mavenLocal()
maven { url 'https://jitpack.io' }
maven { url "https://nexus.inmo.dev/repository/maven-releases/" }
}
}

View File

@@ -11,22 +11,29 @@ private String getCurrentVersionChangelog() {
return changelogDataOS.toString().trim()
}
if (new File(projectDir, "secret.gradle").exists()) {
apply from: './secret.gradle'
def githubTokenVariableName = "GITHUB_RELEASE_TOKEN"
def githubTokenVariableFromEnv = System.getenv(githubTokenVariableName)
def secretFile = new File(projectDir, "secret.gradle")
if (secretFile.exists() || project.hasProperty(githubTokenVariableName) || (githubTokenVariableFromEnv != "" && githubTokenVariableFromEnv != null)) {
if (secretFile.exists()) {
apply from: './secret.gradle'
}
apply plugin: "com.github.breadmoirai.github-release"
def githubReleaseToken = project.hasProperty(githubTokenVariableName) ? project.property(githubTokenVariableName).toString() : githubTokenVariableFromEnv
githubRelease {
token "${project.property('GITHUB_RELEASE_TOKEN')}"
token githubReleaseToken
releaseAssets.from('bot/build/distributions')
owner "InsanusMokrassar"
repo "PlaguBot"
owner = "InsanusMokrassar"
repo = "PlaguBot"
tagName "${project.version}"
releaseName "${project.version}"
targetCommitish "${project.version}"
tagName = "v${project.version}"
releaseName = "${project.version}"
targetCommitish = "${project.version}"
body getCurrentVersionChangelog()
body = getCurrentVersionChangelog()
}
}

View File

@@ -4,19 +4,5 @@ org.gradle.parallel=true
kotlin.js.generate.externals=true
kotlin.incremental=true
kotlin_version=1.6.10
kotlin_coroutines_version=1.6.0
kotlin_serialisation_runtime_version=1.3.2
kotlin_exposed_version=0.37.2
sdi_version=0.6.0
tgbotapi_version=0.38.4
microutils_version=0.9.5
klassindex_version=4.1.0-rc.1
sqlite_version=3.36.0.3
github_release_plugin_version=2.2.12
group=dev.inmo
version=0.5.1
version=10.9.0

56
gradle/libs.versions.toml Normal file
View File

@@ -0,0 +1,56 @@
[versions]
kt = "2.2.20"
kt-serialization = "1.9.0"
kt-coroutines = "1.10.2"
microutils = "0.26.6"
tgbotapi = "30.0.0"
ksp = "2.2.20-2.0.4"
jb-exposed = "0.61.0"
jb-dokka = "2.1.0"
sqlite = "3.50.1.0"
gh-release = "2.5.2"
koin = "4.1.1"
nmcp = "1.2.0"
[libraries]
kt-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kt" }
kt-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kt-coroutines" }
kt-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kt-serialization" }
tgbotapi = { module = "dev.inmo:tgbotapi", version.ref = "tgbotapi" }
tgbotapi-behaviourBuilder-fsm = { module = "dev.inmo:tgbotapi.behaviour_builder.fsm", version.ref = "tgbotapi" }
microutils-repos-exposed = { module = "dev.inmo:micro_utils.repos.exposed", version.ref = "microutils" }
microutils-koin = { module = "dev.inmo:micro_utils.koin", version.ref = "microutils" }
microutils-koin-generator = { module = "dev.inmo:micro_utils.koin.generator", version.ref = "microutils" }
microutils-startup-launcher = { module = "dev.inmo:micro_utils.startup.launcher", version.ref = "microutils" }
microutils-startup-plugin = { module = "dev.inmo:micro_utils.startup.plugin", version.ref = "microutils" }
koin = { module = "io.insert-koin:koin-core", version.ref = "koin" }
jb-exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "jb-exposed" }
sqlite = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite" }
kt-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kt" }
buildscript-kt-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kt" }
buildscript-kt-serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kt" }
buildscript-jb-dokka = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "jb-dokka" }
buildscript-gh-release = { module = "com.github.breadmoirai:github-release", version.ref = "gh-release" }
buildscript-ksp = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" }
[plugins]
nmcp-aggregation = { id = "com.gradleup.nmcp.aggregation", version.ref = "nmcp" }

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -9,14 +9,17 @@ project.version="$version"
apply from: "publish.gradle"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
api "org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlin_serialisation_runtime_version"
implementation libs.kt.stdlib
api libs.kt.serialization
api "dev.inmo:tgbotapi:$tgbotapi_version"
api "dev.inmo:micro_utils.repos.exposed:$microutils_version"
api libs.tgbotapi
api libs.microutils.repos.exposed
api libs.microutils.startup.plugin
api libs.koin
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

View File

@@ -1 +0,0 @@
{"bintrayConfig":{"repo":"PlaguBot","packageName":"${project.name}","packageVcs":"https://github.com/InsanusMokrassar/PlaguBot","autoPublish":true,"overridePublish":true},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/PlaguBot/LICENSE"}],"mavenConfig":{"name":"PlaguBot Plugin","description":"Base dependency for whole PlaguBot project","url":"https://github.com/InsanusMokrassar/PlaguBot","vcsUrl":"ssh://git@github.com/InsanusMokrassar/PlaguBot.git","includeGpgSigning":true,"publishToMavenCentral":true,"developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"}]},"type":"JVM"}

View File

@@ -1,14 +1,14 @@
apply plugin: 'maven-publish'
apply plugin: 'signing'
task javadocJar(type: Jar) {
from javadoc
classifier = 'javadoc'
archiveClassifier = 'javadoc'
}
task sourcesJar(type: Jar) {
from sourceSets.main.allSource
classifier = 'sources'
archiveClassifier = 'sources'
}
publishing {
@@ -50,33 +50,69 @@ publishing {
}
}
repositories {
maven {
name = "bintray"
url = uri("https://api.bintray.com/maven/${project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')}/PlaguBot/${project.name}/;publish=1;override=1")
credentials {
username = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')
password = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
}
}
maven {
name = "sonatype"
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
}
}
}
repositories {
if ((project.hasProperty('INMONEXUS_USER') || System.getenv('INMONEXUS_USER') != null) && (project.hasProperty('INMONEXUS_PASSWORD') || System.getenv('INMONEXUS_PASSWORD') != null)) {
maven {
name = "InmoNexus"
url = uri("https://nexus.inmo.dev/repository/maven-releases/")
credentials {
username = project.hasProperty('INMONEXUS_USER') ? project.property('INMONEXUS_USER') : System.getenv('INMONEXUS_USER')
password = project.hasProperty('INMONEXUS_PASSWORD') ? project.property('INMONEXUS_PASSWORD') : System.getenv('INMONEXUS_PASSWORD')
}
}
}
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
maven {
name = "sonatype"
url = uri("https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/")
credentials {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
}
}
}
}
signing {
useGpgCmd()
sign publishing.publications
if (project.hasProperty("signing.gnupg.keyName")) {
apply plugin: 'signing'
signing {
useGpgCmd()
sign publishing.publications
}
task signAll {
tasks.withType(Sign).forEach {
dependsOn(it)
}
}
// Workaround to make android sign operations depend on signing tasks
project.getTasks().withType(AbstractPublishToMaven.class).configureEach {
def signingTasks = project.getTasks().withType(Sign.class)
mustRunAfter(signingTasks)
}
// Workaround to make test tasks use sign
project.getTasks().withType(Sign.class).configureEach { signTask ->
def withoutSign = (signTask.name.startsWith("sign") ? signTask.name.minus("sign") : signTask.name)
def pubName = withoutSign.endsWith("Publication") ? withoutSign.substring(0, withoutSign.length() - "Publication".length()) : withoutSign
// These tasks only exist for native targets, hence findByName() to avoid trying to find them for other targets
// Task ':linkDebugTest<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
def debugTestTask = tasks.findByName("linkDebugTest$pubName")
if (debugTestTask != null) {
signTask.mustRunAfter(debugTestTask)
}
// Task ':compileTestKotlin<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
def testTask = tasks.findByName("compileTestKotlin$pubName")
if (testTask != null) {
signTask.mustRunAfter(testTask)
}
}
}

1
plugin/publish.kpsb Normal file
View File

@@ -0,0 +1 @@
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/PlaguBot/LICENSE"}],"mavenConfig":{"name":"PlaguBot Plugin","description":"Base dependency for whole PlaguBot project","url":"https://github.com/InsanusMokrassar/PlaguBot","vcsUrl":"ssh://git@github.com/InsanusMokrassar/PlaguBot.git","developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"InmoNexus","url":"https://nexus.inmo.dev/repository/maven-releases/"},{"name":"sonatype","url":"https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}},"type":"JVM"}

View File

@@ -0,0 +1,62 @@
package dev.inmo.plagubot
import dev.inmo.kslog.common.*
import dev.inmo.micro_utils.fsm.common.State
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.sendMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitTextMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.types.IdChatIdentifier
import kotlinx.coroutines.flow.first
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.module.Module
@Serializable
@SerialName("Hello")
object HelloPlugin : Plugin {
@Serializable
data class HelloPluginConfig(
val print: String
)
override fun Module.setupDI(config: JsonObject) {
registerConfig<HelloPluginConfig>("helloPlugin") { null }
}
private sealed interface InternalFSMState : State {
override val context: IdChatIdentifier
data class DidntSaidHello(override val context: IdChatIdentifier) : InternalFSMState
data class SaidHelloOnce(override val context: IdChatIdentifier) : InternalFSMState
}
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
logger.i { "This logic called BEFORE the bot will be started and setup" }
}
override suspend fun BehaviourContextWithFSM<State>.setupBotPlugin(koin: Koin) {
val toPrint = koin.configOrNull<HelloPluginConfig>() ?.print ?: "Hello :)"
logger.d { toPrint }
logger.dS { getMe().toString() }
onCommand("hello_world") {
startChain(InternalFSMState.DidntSaidHello(it.chat.id))
}
strictlyOn { state: InternalFSMState.DidntSaidHello ->
sendMessage(state.context, toPrint)
InternalFSMState.SaidHelloOnce(state.context)
}
strictlyOn { state: InternalFSMState.SaidHelloOnce ->
val message = waitTextMessage().first()
reply(message, "Sorry, I can answer only this: $toPrint")
InternalFSMState.SaidHelloOnce(state.context)
}
}
}

View File

@@ -0,0 +1,11 @@
package dev.inmo.plagubot
import org.jetbrains.exposed.sql.Database
import org.koin.core.Koin
import org.koin.core.scope.Scope
val Scope.database: Database
get() = get()
val Koin.database: Database
get() = get()

View File

@@ -0,0 +1,55 @@
package dev.inmo.plagubot
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.serializer
import org.jetbrains.exposed.sql.Database
import org.koin.core.Koin
import org.koin.core.module.Module
import org.koin.core.scope.Scope
import kotlin.reflect.KClass
/**
* Using [single] to register `T` with serializer [configSerializer]
*
* @param default Will be used if [field] is absent as an alternative way of config allocation. If null passed, error
* will be thrown
*/
inline fun <reified T> Module.registerConfig(configSerializer: KSerializer<T>, field: String?, noinline default: (Scope.(JsonObject) -> T?)? = null) {
single {
val fieldValue = get<JsonObject>().let {
if (field == null) {
it
} else {
it[field] ?: default ?.let { _ ->
return@single default(it)
} ?: error("Unable to take field $field from config")
}
}
get<Json>().decodeFromJsonElement(configSerializer, fieldValue)
}
}
/**
* Using [single] to register config with getting of [serializer] from [kClass]
*
* @param default Will be used if [field] is absent as an alternative way of config allocation. If null passed, error
* will be thrown
*/
@OptIn(InternalSerializationApi::class)
inline fun <reified T : Any> Module.registerConfig(kClass: KClass<T>, field: String?, noinline default: (Scope.(JsonObject) -> T?)? = null) = registerConfig(kClass.serializer(), field, default)
/**
* Using [single] to register config with getting of [serializer] from [kClass]
*
* @param default Will be used if [field] is absent as an alternative way of config allocation. If null passed, error
* will be thrown
*/
inline fun <reified T : Any> Module.registerConfig(field: String?, noinline default: (Scope.(JsonObject) -> T?)? = null) = registerConfig(T::class, field, default)
inline fun <reified T : Any> Scope.config() = get<T>()
inline fun <reified T : Any> Koin.config() = get<T>()
inline fun <reified T : Any> Scope.configOrNull() = getOrNull<T>()
inline fun <reified T : Any> Koin.configOrNull() = getOrNull<T>()

View File

@@ -1,47 +1,48 @@
package dev.inmo.plagubot
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.micro_utils.fsm.common.State
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import dev.inmo.tgbotapi.bot.ktor.KtorRequestsExecutorBuilder
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import kotlinx.coroutines.CoroutineScope
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextWithFSM
import kotlinx.serialization.Serializable
import org.jetbrains.exposed.sql.Database
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.scope.Scope
/**
* **ANY REALIZATION OF [Plugin] MUST HAVE CONSTRUCTOR WITH ABSENCE OF INCOMING PARAMETERS**
*
* Use this interface for your bot. It is possible to use [kotlinx.serialization.SerialName] annotations on your plugins
* to set up short name for your plugin. Besides, simple name of your class will be used as key for deserialization
* too.
*/
@Serializable(PluginSerializer::class)
interface Plugin {
interface Plugin : StartPlugin {
@Deprecated("Deprecated in favor to setupBotClient with arguments")
fun KtorRequestsExecutorBuilder.setupBotClient() {}
/**
* In case you want to publish some processed by your plugin commands, you can provide it via this method
* Will be called on stage of bot setup
*
* @see BotCommand
* @param scope The scope of [org.koin.core.module.Module.single] of bot definition
* @param params Params (in fact, the whole bot config)
*/
suspend fun getCommands(): List<BotCommand> = emptyList()
fun KtorRequestsExecutorBuilder.setupBotClient(scope: Scope, params: JsonObject) = setupBotClient()
@Deprecated("Override other method with receiver BehaviourContext")
suspend operator fun invoke(
bot: TelegramBot,
database: Database,
updatesFilter: FlowsUpdatesFilter,
scope: CoroutineScope
/**
* Override this method in cases when you want to declare common bot behaviour. In case you wish to use FSM, you
* should override the method with receiver [BehaviourContextWithFSM]
*/
suspend fun BehaviourContext.setupBotPlugin(
koin: Koin
) {}
/**
* This method (usually) will be invoked just one time in the whole application.
* Override this method in cases when you want to declare full behaviour of the plugin. It is recommended to declare
* common logic of plugin in the [setupBotPlugin] with [BehaviourContext] receiver and use override this one
* for the FSM configuration
*/
suspend operator fun BehaviourContext.invoke(
database: Database
) = invoke(bot, database, flowsUpdatesFilter, scope)
/**
* This method (usually) will be invoked just one time in the whole application.
*/
suspend operator fun BehaviourContext.invoke(
database: Database,
params: Map<String, Any>
) = invoke(database)
suspend fun BehaviourContextWithFSM<State>.setupBotPlugin(koin: Koin) {
(this as BehaviourContext).setupBotPlugin(koin)
}
}

View File

@@ -1,53 +1,25 @@
package dev.inmo.plagubot
import kotlinx.serialization.*
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializer
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*
private val defaultJson = Json {
ignoreUnknownKeys = true
}
@Serializer(Plugin::class)
object PluginSerializer : KSerializer<Plugin> {
private val polymorphic = PolymorphicSerializer(Plugin::class)
override val descriptor: SerialDescriptor = JsonObject.serializer().descriptor
class PluginSerializer : KSerializer<Plugin> {
override val descriptor: SerialDescriptor
get() = String.serializer().descriptor
@OptIn(InternalSerializationApi::class)
override fun deserialize(decoder: Decoder): Plugin {
val format = (decoder as? JsonDecoder) ?.json ?: defaultJson
val asJson = JsonElement.serializer().deserialize(decoder)
val jsonObject = (asJson as? JsonObject)
val type = (jsonObject ?.get("type") as? JsonPrimitive) ?.contentOrNull
val external = if (type != null) {
try {
Class.forName(type) ?.kotlin ?.serializerOrNull()
} catch (e: Exception) {
null
}
} else {
null
}
return if (jsonObject != null && external != null) {
format.decodeFromJsonElement(
external as KSerializer<Plugin>,
JsonObject(jsonObject.toMutableMap().also { it.remove("type") })
)
} else {
format.decodeFromJsonElement(
polymorphic,
asJson
)
}
val kclass = Class.forName(decoder.decodeString()).kotlin
return (kclass.objectInstance ?: kclass.constructors.first { it.parameters.isEmpty() }.call()) as Plugin
}
@OptIn(InternalSerializationApi::class)
override fun serialize(encoder: Encoder, value: Plugin) {
val serializer = (value::class.serializerOrNull() ?: polymorphic) as KSerializer<Plugin>
serializer.serialize(encoder, value)
encoder.encodeString(
value::class.java.canonicalName
)
}
}

View File

@@ -2,7 +2,12 @@ String[] toInclude = [":bot", ":plugin"]
rootProject.name = 'plagubot'
toInclude.each {
include (it)
project(it).name = "${rootProject.name}${it.replace(":", ".")}"
toInclude.each { originalName ->
String projectDirectory = "${rootProject.projectDir.getAbsolutePath()}${originalName.replace(":", File.separator)}"
String projectName = "${rootProject.name}${originalName.replace(":", ".")}"
String projectIdentifier = ":${projectName}"
include projectIdentifier
ProjectDescriptor project = project(projectIdentifier)
project.name = projectName
project.projectDir = new File(projectDirectory)
}

View File

@@ -4,13 +4,16 @@
"driver": "org.sqlite.JDBC",
"username": "OPTIONAL username",
"password": "OPTIONAL password",
"initAutomatically": false
"reconnectOptions": {
"attempts": 3,
"delay": 1000
}
},
"botToken": "1234567890:ABCDEFGHIJKLMNOP_qrstuvwxyz12345678",
"plugins": [
{
"type": "Hello",
"parameter": "Example"
}
]
}
"dev.inmo.plagubot.HelloPlugin"
],
"helloPlugin": {
"print": "Hello World"
}
}