Commit Graph

3269 Commits

Author SHA1 Message Date
sandtechnology
3ec8e552cd
[core] Add encryption SPI & T544 support (#2566)
* Initial design for encryption SPI & T544 support

* Fix missed vararg

* Move EncryptWorkerService to internal spi

* Add useAndroid val to QQAndroidClient and rebase to the latest dev branch

* Remove docs and annotations (Throws and MiraiExperimentalApi)

* Remove unwanted changes

* Remove redundant runBlocking in tlv544

* Tweak the file annotation location

* Remove suspend modifier for doTLVEncrypt

* Disable DebuggingProperties

* Fix format

* Remove empty line

* Remove empty line again

* Use instance field directly

* Add Volatile annotation to instance

* Use atomicRef instead of field

* Use kotlin lambda for readability

* wip

* Improve EncryptService API

* Add possible values

* remove docs

* Add key BOT_PROTOCOL

---------

Co-authored-by: Him188 <Him188@mamoe.net>
2023-06-04 00:01:54 +01:00
微莹·纤绫
97f85bc8b9
[core] ForwardMessage refine by light app (#2675) 2023-05-28 19:20:12 +01:00
cssxsh
3dfe86bbe0
fix: digest message (#2672)
fix: unsigned int
2023-05-27 12:40:48 +01:00
StageGuard
60d360baad
[core] Update login protocol, deprecate DeviceInfo constructor and serializer (#2613)
* [core] update protocol

* [core] fix t106 decryption key

* [core] handle t543

* [core] revert t106

* [core] revert native test pow data

* [core] split build version and apk version name

* [core] pass time to t1 instead of time diff

* [core] remove unused t106 writer & rename param ip to ipv4 of t1 and t106

* [core] implement qimei for t545
TODO: aes and rsa crypto for nativeMain

* [core] fix base64 decode for android in rsa

* [core] fix unix timestamp parsing on native and add more tests

* [api] DeviceInfo move `androidId` to main constructor and adjust test.

* [api] do not request qimei when protocol is neither  ANDROID_PHONE nor ANDROID_PAD

* [api] implement aes crypto for native target

* [api] rsa crypto for multi-platform

* [api] crypto test

* [api] move freePointer util

* [api] openssl api compatibility

* [core] add explicit `androidId` param

* [core] remove unused `tlvCount`

* [core] optimize crypto

* [core] move Qimei to network package

* [core] move appId to protocol

* [core] lazily initialize qimeiLogger

* [core] write byte array to BIO mem

* [core] move qimei to client, add direct serializer for DeviceInfo

* [core] optimize DeviceInfoDelegateSerializer

* [core] real user-agent when requesting qimei

* [core] use `DeviceInfo.version.release`

* [core] remove unused wtlogin packet

* [core] do what constructor serializer should do

* [core] fix endless cache validation caused by not upgrading device info file.

* [core] request qimei before fast-login

* [core] tlv order

* [core] remove wrong tests and print more detail when deserialize failed.

* [core] device info upgrade for native

* [core] request qimei after validating cache

* [core] DeviceInfo compatibility

* [core] DeviceInfo test name

* [core] compatibility serializer

* [core] disable rsa crypto test on android unit test

* [core] move rsa impl to jvmBase

* action

* import

* api dump

* api dump

* revert wrong api dumps

* [core] Deprecate DeviceInfo constructor and serializer, provide `serializeToString` and `deserializeFromString` for replacement

* rerun ci

* optimize

* use serializer directly

* optimize test

* revert

* [core] CacheValidator use `DeviceInfo.serializeToString()` instead of direct serializer

* Remove `println` in `DeviceInfoManager`

* Add legacy deserialize overload for ABI compatibility

* Remove uncompleted docs for DeviceInfo

* Suppress DeviceInfo deprecation warnings for internal usages

---------

Co-authored-by: Him188 <Him188@mamoe.net>
2023-05-21 13:45:46 +01:00
Him188
dafa25d611
[core] Simplify and stabilize BaseService and AudioToSilkService (#2658)
* [core] Simplify and stabilize BaseService and AudioToSilkService

* fix

* api dump
2023-05-21 00:24:51 +01:00
Him188
b82e938b2c
[build] Fix checkAndroidApiLevel tasks when building without ADK 2023-05-06 11:20:49 +01:00
Him188
363d1f7ece
Remove module-level opt-ins, add @OptIn explicit in use-sites;
added some opt-in markers on API which should have:

- `appendMiraiCodeTo`

Made API stable (otherwise they require too heavy opt-ins):
- MiraiConsoleImplementation$ConsoleLaunchOptions
- LowLevelApi
2023-05-06 11:04:31 +01:00
Him188
bda5d54bd3 [core/auth] Wrap exception from BotAuthorization as BotAuthorizationException; add tests 2023-05-04 16:36:28 +01:00
Him188
b18e62b3b6 [core] SsoProcessor.loginSuccess: use sendRegister to allow being overriden for tests 2023-05-04 16:36:28 +01:00
Him188
0e625d3368 [core] OnDemandChannel: Ensure scope is closed on exceptional cases:
[core] OnDemandChannel: Ensure channel close and emit shares same behavior

[core] OnDemandChannel: Ensure channel is closed properly when producer throws an exception

[core] OnDemandChannel: Ensure coroutine scope cancelled when producer coroutine throws exception,

also added more tests
2023-05-04 16:36:28 +01:00
Him188
87fbaa4fb2 [core] Revise OnDemandChannel, improve state abstraction:
[core] Start producer coroutine immediately on `expectMore` and yield

Improve docs for OnDemandChannel

Rename factory function `OnDemandReceiveChannel` to  `OnDemandChannel` to better cover its meaning

Create deferred lazily in Producing state

Rename ProducerState to ChannelState

fix atomicfu bug receiveOrNull

Add docs (WIP, to be rebased)

[core] OnDemandChannel: Catch Throwable in `receiveOrNull` to prevent possible failures
2023-05-04 16:36:28 +01:00
Him188
99f592d614 [core] Move Latch and OnDemandValueScope to mirai-core-utils,
and rename OnDemandValueScope to OnDemandSendChannel and OnDemandReceiveChannel
2023-05-04 16:36:28 +01:00
Him188
36d90c57fe [core] Add UtilsLogger in mirai-core-utils module to bridge logging,
also added delegations in mirai-core and mirai-core-api.
2023-05-04 16:36:28 +01:00
Him188
26ea98db6a [core] Extract SafeBotAuthSession implementation from AuthControl 2023-05-04 16:36:28 +01:00
Him188
0c24053198 [core] AuthControl: require explicit .start() instead of launching job in constructor 2023-05-04 16:36:28 +01:00
Him188
10e731f260 [core] CoroutineOnDemandValueScope: remove CreatingProducer state 2023-05-04 16:36:28 +01:00
Him188
d263a9ee29
[core] MiraiProtocolInternal: Use setters 2023-05-02 21:41:22 +01:00
Him188
84d03c9a71 [core] Set minimum Android API level to 21 2023-05-02 16:17:48 +01:00
Him188
2ef89d2b3f [build] Do not apply Android-relevant plugins if Android target is not enabled 2023-05-02 16:17:48 +01:00
Him188
178ca6c1b5 [build] Rewrite shadow relocation; fix dependency graph issues with Android, and improve build performance:
- Generate relocated JARs with classifier `relocated`, instead of replacing the output of `:jar` task.

- Create `JvmRelocated` publications to publish relocated artifacts.

- Patch Kotlin Metadata and Maven Pom for the added publication.

- Updated deps test to be more strict
2023-05-02 16:17:48 +01:00
Him188
40d4957837 [core/android] Implement mirai-core tests for Android target with AndroidSDK 2023-05-02 16:17:48 +01:00
Him188
4ed551027a [build] Support both configuring Android targets by Android SDK or JVM
- try to fix sdk dir when android is desired
- Do not printAndroidNotInstalled multiple times
2023-05-02 16:17:48 +01:00
Him188
2cf97a181f [build] Use JUnit5 on Android 2023-05-02 16:17:48 +01:00
Him188
a2d50ec03a [build] Relocate ktor only for jvm, not for Android 2023-05-02 16:17:48 +01:00
Him188
164f621427 [build] Fully support Android target; Update to Gradle 8.0 2023-05-02 16:17:48 +01:00
Him188
fc549d380f
[core] Make properties mutable in MiraiProtocolInternal 2023-05-01 23:11:46 +01:00
Him188
a988d442e2
[core] Add PacketReplier DSL for core tests 2023-05-01 22:56:34 +01:00
Him188
f469e889d2
[build] Enable atomicfu compiler plugin for mirai-core and mirai-core-api, but disable transformations for JVM, #2315 2023-05-01 11:09:28 +01:00
Him188
6798de8093
[core] Make ImageUploadedChecker not fun interface since Kotlin doesn't support suspend fun in that 2023-05-01 11:08:21 +01:00
Him188
d2d2f4844d
[core] Fix minor compiler warnings
- unused variables
- requires opt-in
2023-05-01 11:08:04 +01:00
Him188
578d1a9d48
[core] CoroutineOnDemandValueScope: fix exception message when emit/receive while producer is already finished 2023-04-16 10:31:03 +01:00
Him188
a1d8d744d0
[core] CoroutineOnDemandValueScope: fix emit when state is ProducerReady 2023-04-16 10:31:03 +01:00
Him188
1b122190f1
[core] CoroutineOnDemandValueScope: ignore multiple finishImpl 2023-04-16 10:31:03 +01:00
Him188
30b3472460
[build] Fix macOS CI, use pre-installed OpenSSL 2023-04-15 14:58:57 +01:00
cssxsh
71e9de3608
[core] 支持获取群公告图片 URL (#2619)
* fix: announcement protocol

* add: api dump
2023-04-13 11:57:04 +01:00
cssxsh
50d37c484a
[core] Fix group active protocol (#2610) 2023-04-05 11:06:16 +01:00
Him188
c29fe9d244
[core] Remove useless limitation on QR query, fix QR login for overseas users 2023-04-04 21:08:31 +01:00
Karlatemp
ecbb9b2672
[core/logging] Drop control characters in message log 2023-04-04 17:02:25 +08:00
Karlatemp
89fa2f7ffb
[core] Fix private message source target 2023-03-29 22:53:09 +08:00
Karlatemp
b8321870aa
[core] Code style & comments update 2023-03-29 22:53:07 +08:00
Karlatemp
8d9c820a92
[core] Fix group roaming message fetching 2023-03-29 22:53:06 +08:00
Karlatemp
275d9f8f6e
[core] Fix replying unavailable member's message 2023-03-29 22:53:05 +08:00
Karlatemp
07164cc79b
[core] Fix group roaming message fetching 2023-03-29 22:53:04 +08:00
Karlatemp
8c5a22a14e
[core] Try to fix rand id fetching 2023-03-29 22:53:02 +08:00
Karlatemp
00486e7900
[core] Add internal message when failed to transform internal message to facade message 2023-03-29 22:53:01 +08:00
Karlatemp
ec5870e0b3
[core] Get group incoming message source raw data directly 2023-03-29 22:53:00 +08:00
Karlatemp
fe14600018
[core] Private quote reply decode 2023-03-29 22:52:59 +08:00
Karlatemp
648997b545
[core] Fix offline message source ids 2023-03-29 22:52:59 +08:00
Karlatemp
1169d7cf57
[core] Fix quote replying; Fix message source time 2023-03-29 22:52:58 +08:00
Karlatemp
e2d7332ac0
[core] Add QRCodeLoginListener.onCompleted 2023-03-27 00:55:54 +08:00
微莹·纤绫
434ef0cc39
Tlv writer (#2569)
* [core] TlvMapWriter

* [core] bind tlv writing with writer

* [core] Add checking to avoid wrong nest writing

* [core] Drop Int.invoke

* [core] Merge with dev

* [core] Update style
2023-03-26 23:51:03 +08:00
sandtechnology
0f1bddcb24
[core] Fix token not saving after refresh token (#2590) 2023-03-25 14:08:20 +00:00
cssxsh
b37fe6c2ed
update: protocol ANDROID_WATCH 2.0.8 (#2592) 2023-03-24 19:10:13 +00:00
sandtechnology
baf9ee4bf7
[core] Add missed refresh token logic for OnlinePush.SidTicketExpired (#2584) 2023-03-22 03:01:43 +00:00
Him188
c74e9d2858
[build] Make mirai-core AbstractTest public, and add dependsOnCoreJvmTest in buildSrc 2023-03-21 18:12:04 +00:00
sandtechnology
7e20883a08
[core] Fix OnlinePush.SidTicketExpired logic (#2563)
* Fix OnlinePush.SidTicketExpired logic

* Add missed responseCommandName
2023-03-21 15:00:26 +00:00
cssxsh
f4fa2cabf4
[core] feat: essence message setting (#2314)
* feat: remove essence message

* feat: Essences

* add: share and remove

* fix: impl

* fix: arguments

* feat: image url to image

* add: doc

* fix: doc

* Copyright: 2023

* remove: method removeEssenceMessage

* feat: lazy load source

* add: no parse

* add: sendAndExpect try

* fix: remove throw

* fix: parse IMAGE_MD5_REGEX
2023-03-21 14:53:23 +00:00
cssxsh
c016b822e7
[core] 修复群公告查询已阅读人员列表只能获取前 50 个的问题 (#2530) 2023-03-21 14:45:42 +00:00
sandtechnology
28b1032acd
[core] Handle rare case on packet pipeline (#2450)
* Handle rare case on packet pipeline
Fix #2449, should help #1603

* Fix and improve tips and improve the readability of code

* Improve wording of tips

Co-authored-by: Him188 <Him188@mamoe.net>

* Change d2Key error type to PROTOCOL_UPDATED

* Reformat code

---------

Co-authored-by: Him188 <Him188@mamoe.net>
2023-03-21 14:43:48 +00:00
NoMathExpectation
64f80949ac
Fixed message sending ignoring modifies via MessagePreSendEvent. (#2525) 2023-03-21 13:10:47 +00:00
Him188
427c37e649
[build] Update to Kotlin 1.8.10 2023-03-19 03:18:34 +00:00
StageGuard
78d0b4fd54
QRCode login support & Introduce new authorization factory (#2502)
* [core] process `wtlogin.trans_emp` to support qrcode login

* [core] fix `wtlogin.trans_emp` protocol

* [core] optimize QRCodeLoginProcessor logic

* [core] fix `wtlogin.trans_emp` outgoing packet

* [core] cancel login when logging a bot which is inconsistent from bot factory

* [core] ignore `flag3` check on ANDROID_WATCH & name `flag1` and `flag2`

* [core] provide default `QRCodeLoginListener` for jvm

* [core] don't catch IllegalStateException in QRCodeLoginProcessor

* [core] Use `LoginSolver.createQRCodeLoginListener()` instead of property; Rename configuration name

* [core] Code improvement

* [core] remove qrcode state lock

* [core] ignore `flag3` when command is `wtlogin.trans_emp` in packet codec

* [core] enable qrcode login for macos

* [core] remove debug property in log

* [core] reformat code

* [core] rename `TransEmpResponse` to `Response`

* [core] assert `flag3Exception` not null first

* [core] remove arg client

* [core] update qrcode login notes

* [core] set custom qrcode size

* [core] Draft BotAuthorization

* [core] make SecretsProtection mpp

* [core] BotAuthorization.byXXX

* [core] Move QRCodeLoginListener to `.auth`

* [core] Protect data of BotAccount

* [core] Add SelectorRequireReconnectException

* [core] Implementation of BotAuthorization

* Revert changes of BotConfiguration

* api dump

* [core] remove passwordMd5 in `BotAccount`

* [mock] Add new bot factory function to mock bot factory

* Delete LoginCommandTest

* [core] Improve QRCode render

* [core] Introduce UnsupportedCaptchaMethodException & UnsupportedQRCodeCaptchaException

* api dump

* update docs

* [core] update `DebugRunHelper`

* [core] add simple block for BotAuthorization

* api dump

* Rename `canDoQRLogin` to `supportsQRLogin`, and specify argument names for MiraiProtocolInternal

* Remove `phoneNumber` parameter from BotAccount

* Make `BotAccount.<init>` with String password parameter TestOnly

* Rename `InconsistentBotException` to `InconsistentBotIdException`

* Rename `QRCodeLoginListener.onStatusChanged` to `QRCodeLoginListener.onStateChanged`

* Rename `BotAuthorizationResult` to `BotAuthResult`

* Rename BotAuthComponent, move internal APIs to internal module

* Logic fixup

* doc update

* QRCodeLoginListener.qrCodeStateUpdateInterval & onIntervalLoop

* console login with BotAuthorization

* update testing

* Update mirai-core-api/src/jvmMain/kotlin/utils/LoginSolver.jvm.kt

* Move AuthControl outside SsoProcessor

* Redesign auth

* Add initialTicket to producerCoroutine

* Revert protocol changes of MACOS

* Fix latch death locking

* Fix CoroutineOnDemandValueScope.receiveOrNull exceptional finish

* Fix exception collecting

* Fix DefaultBotAuthorizationFactory loading

* [core] qrcode login for IPAD protocol

* Revert "[core] qrcode login for IPAD protocol"

This reverts commit c1136a8798.

---------

Co-authored-by: Karlatemp <kar@kasukusakura.com>
Co-authored-by: Him188 <Him188@mamoe.net>
2023-03-18 13:52:31 +00:00
cssxsh
e5ff458a5d
fix: address as NettyChannelException message (#2576)
* fix: address as NettyChannelException message

* fix: message
2023-03-16 22:23:42 +08:00
cssxsh
b6b1059107
update: MiraiProtocol IPAD MACOS (#2575) 2023-03-15 14:15:34 +00:00
Eritque arcus
3ff2737b3c
Add fallback solution for Services (#2511)
* add fallback solution for Services

* use castUp

* throw exception when prop doesn't match

* cannot use castUp

* improve codes

* improve name of functions

* add both

* add override

* solve conflicts

* [core] Move MiraiCoreServices to common

* [core] Improvement

* update var names

* update func names

---------

Co-authored-by: Karlatemp <kar@kasukusakura.com>
2023-03-11 18:12:56 +08:00
ヒューマンワーキン
a0d9047b7b
修复 dumpTlvMap 不正确的返回值 (#2557)
* 修复 dumpTlvMap 不正确的返回值

* Update WtLogin.kt

* Update WtLogin.kt

注意力涣散.jpg
2023-03-08 11:58:24 +00:00
sandtechnology
01d2851af1
Update android protocol version (#2551)
Thanks to MiraiGo.
Fixes #2545,#2492,#2453
2023-03-07 12:15:20 +00:00
Karlatemp
4d9f6e88f9
[core] Fix polymorphic serialization 2023-02-20 22:09:39 +08:00
cssxsh
bec756e0bf
[core] fix: announcements cookie (#2512) 2023-02-19 11:50:02 +00:00
sandtechnology
f4667fe1ef
[core] Handle TimeoutCancellationException when resuming connection. Fix #2504, fix #2488 (#2505)
* #2504,#2488 handle TimeoutCancellationException when resuming connection

* Remove unnecessary code and fix wording

* Use yield() instead of delay

* Use yield() instead of delay
2023-02-19 11:49:41 +00:00
Karlatemp
e686a23f40
[core] Fix offline message source quote replying; fix #2501 2023-02-16 23:06:23 +08:00
Him188
940e76aa95
[core] Fix AbstractProcessorPipeline.registerBefore, do addFirst instead of add 2023-01-29 08:33:54 +00:00
sandtechnology
cc7f35519e
Update login protocol (#2433)
* Update login protocol
Still need testing

* Turn off debug option and make t547 null when failed

* Fix wrong convert method and improve tips

* Remove unused part and improve tips

* Fix typo

* Inline resultStatus for performance

* Rename pow to PoW, the name should be "Proof of Work"

* Add shadow and deps-test for kt-bignum

* Try to fix deps-test

* Fix deps-test again
2023-01-18 17:41:21 +08:00
sandtechnology
53f1971d94
[core] Generate and handle tgtgtKey correctly, fix #2418 (#2419)
* Generate and handle tgtgtKey correctly, fix #2418

* Optimize the code readability of WtLogin9

* Add utility method to write t106 with A1
2023-01-13 23:36:10 +00:00
sandtechnology
e7bcb190a7
Update ANDROID_PHONE and ANDROID_PAD protocol (#2423)
Updated From MiraiGo:a30750849d
2023-01-13 12:28:28 +00:00
Him188
f04c623658 [core] Implement a more efficient algorithm to fetch roaming messages for group:
- Added `RoamingMessagesImplGroup`.
- Dump API changes for Group RoamingMessages.
- [mock] Fix MockRoamingMessages missing MessageSource
- [core] Convert hierarchical TimeBasedRoamingMessagesImpl to common, to reduce code complexity
2023-01-05 02:33:27 +00:00
Him188
db601928ea [core] Rename CommonRoamingMessagesImpl to TimeBasedRoamingMessagesImpl. Extract RoamingMessagesImplFriend 2023-01-05 02:33:27 +00:00
StageGuard
2d0b4d470a [core] Proposal implementation of RoamingSupported for Group 2023-01-05 02:33:27 +00:00
StageGuard
5a73c75554 [core] decode MessageSvc.PbGetGroupMsg and OidbSvc.0x88d_0 2023-01-05 02:33:27 +00:00
cssxsh
2cffb7a4a4
[core] feat: RockPaperScissors (#2220)
* [core] feat: RockPaperScissors

Co-authored-by: Karlatemp <kar@kasukusakura.com>

* docs update

* rename `eliminate` to `eliminates`

Co-authored-by: Karlatemp <kar@kasukusakura.com>
2023-01-03 10:00:32 +08:00
Him188
eea2ef509d
[core] Delete cache file if exception occurred while loading GroupMemberListCache. Fix #2399 2023-01-02 16:13:01 +00:00
微莹·纤绫
553ea9abbc
[core] Introduce CacheValidator for validating caches (#2388)
* [core] Export DeviceInfo.serializer() to mirai-core

* [core] Introduce CacheValidator for validating caches
2023-01-02 15:39:36 +00:00
Him188
0a7df909ca
[core] AbstractRealNetworkHandlerTest: close bot after each test only if bot was created 2022-12-27 17:39:46 +00:00
Him188
e3e71e1d1f
[core] Do logout only if firstLoginSucceed 2022-12-27 17:39:46 +00:00
Him188
04b16fe2e4
[core] Ensure Bot.login always show actual login cause whenever a failure in Bot.close happens 2022-12-27 17:29:26 +00:00
Him188
2252683cee
[core] Ensure Bot's CoroutineScope is always cancelled on Bot.close if network.close threw an exception 2022-12-27 17:28:52 +00:00
Him188
38162db477
[core] Add test rethrow exception caught during Bot_login, helps #2338 2022-12-27 16:54:05 +00:00
Him188
2accabef9e
[core] Implement correct TlvMap dump for unrecognized login errors 2022-12-27 16:29:42 +00:00
Him188
7908edb57b
[core+console] Raise deprecation level for 2.14, API including:
- EventChannel.asChannel
- (internal) syncFromEventImpl
- EmptyMessageChain
- GroupEntranceAnnouncementChangeEvent
- MiraiConsole.createLogger
- SingletonExtensionPoint
2022-12-27 15:53:12 +00:00
Him188
76a70f596f
[core] Raise deprecation level for RemoteFile to ERROR (for v2.14) 2022-12-27 14:34:41 +00:00
cssxsh
60dd4b5be6
[core] Add friendGroupId default value (#2403)
Fixes https://mirai.mamoe.net/topic/1895
2022-12-24 14:22:14 +00:00
Karlatemp
d9f3fe616c
[core] Fix ForwardMessage rendering on iOS; fix #1575 2022-12-15 00:22:45 +08:00
Karlatemp
3abef93fd8
[core] Fix jceData of MessageSource from ForwardMessage; fix #2342 2022-12-11 22:29:10 +08:00
Karlatemp
c77ed79b12
[core] Encode html entities for forward message; fix #2241 2022-12-11 22:26:06 +08:00
Karlatemp
c52e99dd87
[core] Include more details in error message to help debug. 2022-12-08 23:44:30 +08:00
Karlatemp
e65f4e65c8
[core] Improve error message of NormalMember.modifyAdmin(); #2370 2022-12-03 19:59:48 +08:00
Karlatemp
b5fcbe99fb
[core] Improve error message of NormalMember.modifyAdmin(); #2370 2022-12-03 19:30:15 +08:00
Him188
60bbcf6e2c
[core] Revert "Review atomic calls and enable atomicfu compiler. Close #2315", due to atomicfu does not behave correctly when mirai-console depends on mirai-core-utils. Fixes #2329.
This commit reverts part of commit 564a7ce8f8
2022-11-27 20:08:21 +00:00
Him188
3360347ca2 [build] Fix dependency exclusion for builds when IDEA_ACTIVE 2022-11-27 15:25:18 +00:00
Him188
76cee371a9 [build] Register native binaries for mirai-core only to speed up builds 2022-11-27 15:25:18 +00:00