mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 05:12:17 +00:00
Compare commits
374 Commits
1.0.6
...
1.1.0-ntrn
Author | SHA1 | Date | |
---|---|---|---|
59d762eecf | |||
e891bc8512 | |||
494c70f2f8 | |||
7baf459b2a | |||
36a09ca088 | |||
926c4659f6 | |||
cb7c68f36c | |||
72af39208c | |||
042f4bd330 | |||
9aef71b09f | |||
9cbe755520 | |||
df02f9f872 | |||
5cbb695a66 | |||
c014e85faa | |||
4a396b0935 | |||
d59fcf9f6a | |||
cdc664f44a | |||
ad313f384c | |||
b6a510ce05 | |||
bed5947909 | |||
fb6578d243 | |||
d33cace7aa | |||
659d4e5da4 | |||
ac2aee8c0e | |||
0faada7b5a | |||
680317da13 | |||
7782feb6ac | |||
d66358a1f3 | |||
824f280b3a | |||
6936262d62 | |||
0955267ee5 | |||
f3da62fa74 | |||
abbac6315c | |||
0cf10eabd6 | |||
8c33267887 | |||
f030104ff2 | |||
ee5fcc3403 | |||
5e819179b4 | |||
ea206faf4f | |||
5adfc544a2 | |||
bdb75841cf | |||
a3dc0d06b2 | |||
3664352f23 | |||
2770979fee | |||
6c9b282c6a | |||
3a07116093 | |||
be58c368e9 | |||
a95d8d85e8 | |||
1d035fa378 | |||
7d0b60271e | |||
d38777d06a | |||
7bacea3288 | |||
ca47f9dbdf | |||
cb4268edef | |||
c16f9d543c | |||
93c49953cf | |||
883e949cc1 | |||
a528030cbb | |||
bbdfb7c04e | |||
1afc0ac6a6 | |||
638bf72392 | |||
07364c8298 | |||
ee6e13a5bb | |||
c3934778c7 | |||
13a49dd70b | |||
5637db43be | |||
69cdbad643 | |||
a06708bf95 | |||
2ac0003166 | |||
d92d1daffb | |||
27f837adbe | |||
661680e60b | |||
54b7eb95a8 | |||
265fff3cd2 | |||
8ca0a3815a | |||
da6d34c53e | |||
61ffb37951 | |||
593f461ffe | |||
12d594697d | |||
352aa5f737 | |||
9546e90bec | |||
26b4d95ad8 | |||
4a6109fbe6 | |||
d6142173c9 | |||
38cf806b40 | |||
82269bb171 | |||
fc0d7a62af | |||
60fdfd9071 | |||
1f620bcc06 | |||
737acfa41b | |||
3619cba33c | |||
52ec43abf8 | |||
e96c356de4 | |||
bbdb0a65fb | |||
ec56e32be1 | |||
4dc83fdeba | |||
541422a43e | |||
cb7bf00e17 | |||
a3171b3111 | |||
02626489eb | |||
a9a2e9a3dd | |||
964c55de31 | |||
befb4a2bef | |||
210609bd7b | |||
3e03d4782d | |||
675a7a5321 | |||
a78b5cab23 | |||
252a3527a8 | |||
ea4cf06edf | |||
1424efd7f8 | |||
eb807a0332 | |||
e9a3a82b68 | |||
fca66f3259 | |||
92ebe0c6a8 | |||
6b1147d065 | |||
720313124c | |||
68ea62ea0b | |||
5584a41af0 | |||
0bca46bba3 | |||
4f1d19fcbd | |||
9a85e4d537 | |||
fac92d8094 | |||
605f58da47 | |||
d22f3ad1cb | |||
46ed966c18 | |||
623dc5da07 | |||
bd6d4f046c | |||
9ad66f2f92 | |||
b4c40e236a | |||
9bbcc2f160 | |||
00b355b877 | |||
071ddbb69a | |||
4d5c054bc4 | |||
87629666f2 | |||
75633f78c4 | |||
c940aea153 | |||
18126b1fda | |||
e9884a5fa8 | |||
aa7b241dba | |||
c70f3eabfe | |||
1c65aab673 | |||
a5cdd64686 | |||
b07ca5bd03 | |||
8f8580d542 | |||
0ed4480878 | |||
c3e0031aa4 | |||
388c963e88 | |||
4283651b1e | |||
50d7dfa06d | |||
b3a2e605fb | |||
14bf5fc0a2 | |||
2c8b57a7dc | |||
8e6c167987 | |||
2c8094c8c8 | |||
62385d6f62 | |||
3b210d7ed0 | |||
63ce2d40bd | |||
36f8b6e54b | |||
58413044e9 | |||
3395cd9d95 | |||
494b1f1fd0 | |||
cf943fd13a | |||
9608b46799 | |||
502956e3ec | |||
27b4c26da7 | |||
65f54360f8 | |||
9a9fad975f | |||
7153b21cd4 | |||
fdb2486090 | |||
d60b2a25d1 | |||
2d8dde6951 | |||
78fd60dade | |||
80dbf6af28 | |||
1e53753b5a | |||
e727877268 | |||
63b69df3ea | |||
b03e02675b | |||
e68a1ffd37 | |||
fb00e5c1ff | |||
7bfb9b7b61 | |||
c43689822b | |||
7952453137 | |||
2f61f6da00 | |||
db252b6b6c | |||
137c354acc | |||
1c7f6bd034 | |||
649d8771ca | |||
af7b0f732e | |||
12738fd52c | |||
b165e1c0c2 | |||
29c1ad8bc9 | |||
262af4108b | |||
a22dc50f14 | |||
e629981218 | |||
103381c17a | |||
7540ef04bb | |||
30b48c6677 | |||
48e4648110 | |||
b10b10d4a2 | |||
036f8a49ac | |||
67f52b8df0 | |||
dd1b909bb0 | |||
72c3c7bdf7 | |||
e0e7a9fc2e | |||
b3d853dec3 | |||
e0a4aad3cd | |||
328e656859 | |||
c97f79335a | |||
e07e75747a | |||
9482641c38 | |||
a485e72ddf | |||
c7265ba628 | |||
c39c2a172f | |||
64b7b00253 | |||
ec132d224e | |||
9c9fbfa753 | |||
4b5932b319 | |||
0c91028469 | |||
48b720bdd7 | |||
2038d81ce8 | |||
81be383b5f | |||
0fb88e3e44 | |||
e92b04ad0f | |||
160d1a11ac | |||
b9cfe73eae | |||
8d6d984849 | |||
25fe9fab37 | |||
ba7058a838 | |||
0858395e60 | |||
fdd769d9ff | |||
f47ae69653 | |||
f311ae3797 | |||
5a941f889f | |||
69e50c6f93 | |||
f7ac3a5d23 | |||
b6b54a805e | |||
131f56a468 | |||
e45e9e7fa0 | |||
cac0aad1f2 | |||
2c1bd9e726 | |||
2645e8f451 | |||
e92c227bba | |||
a31fe92c0b | |||
70cb876439 | |||
9aa4c37354 | |||
d44150ea1a | |||
0360c81bee | |||
cb904c1f1c | |||
bc754db959 | |||
8df799a6e4 | |||
71dd9469ca | |||
79788d2cdc | |||
c28c9981c4 | |||
8fadd0016a | |||
77504d68fd | |||
1490450178 | |||
88beaf8b6f | |||
df25b0bc76 | |||
d07eea7766 | |||
5000453002 | |||
35c82fcc51 | |||
89a4912ed7 | |||
aeabc66067 | |||
ccbfc9a1e1 | |||
31936feb98 | |||
538db69754 | |||
25ea5bd6a8 | |||
460cd84258 | |||
3f9613c43c | |||
34eccda233 | |||
741d2c7a84 | |||
6ee5ceb321 | |||
6107ec6ffb | |||
4ef014a8ac | |||
135a7c2f56 | |||
420f11784d | |||
951e7462c4 | |||
1b0550b5e1 | |||
919c4a7d80 | |||
dcb2b0a26f | |||
d388e5df0c | |||
5776524579 | |||
1d0a0731fb | |||
4dafa75944 | |||
85cdc86b07 | |||
cd19426d1b | |||
48b1b40e1c | |||
50d469cc45 | |||
37f74d5284 | |||
adb7b12c16 | |||
27791cc848 | |||
bd45523e25 | |||
c0f2242679 | |||
c309a2b3ed | |||
48c9048a00 | |||
4d2f7a794b | |||
ab6e431872 | |||
9423df2670 | |||
a2b3e42eee | |||
d9a045bbf0 | |||
42ca17339e | |||
003c4d4456 | |||
ec39aa7bc3 | |||
4e3870a512 | |||
97534b01a6 | |||
61bed61bfb | |||
a0ff4782db | |||
41dd1de8f8 | |||
fa6634d6af | |||
6201d12f5f | |||
b2adc5cedf | |||
0bb871bf01 | |||
dc969440ee | |||
b9b6e133d0 | |||
b5a9884448 | |||
bffb7caf04 | |||
2c3466b4c3 | |||
007e5fef2f | |||
48773cc47c | |||
b2ad4438ab | |||
2fdcfe332b | |||
7d8772ebf6 | |||
2a75160ef8 | |||
76bd58d984 | |||
39120bdeae | |||
7b07698f7b | |||
5c10a5a04e | |||
3a0dc41329 | |||
64c800c945 | |||
ecb3cea5a5 | |||
8e0ae6f85b | |||
9d893b481d | |||
85aaa54e4e | |||
c6dad5677c | |||
80a4a208b9 | |||
ae663e6b2e | |||
780f3577a5 | |||
3518f974cc | |||
911b003f7f | |||
69bc80e9b3 | |||
da0b74db1a | |||
7212938df3 | |||
ae1e78b267 | |||
b7266e490f | |||
6b4a429821 | |||
4a4507dfcd | |||
f63bcabf1b | |||
4932b36ee1 | |||
8c307c4f6e | |||
8d8846fafb | |||
544e216ddb | |||
4fedab719b | |||
75a567d5cd | |||
1a814e565a | |||
5ea260c24b | |||
2d57dc021d | |||
dabe2ea886 | |||
673902e514 | |||
5062ff7c3a | |||
0de6f851a6 | |||
c758b1576d | |||
5ba8bd11e2 | |||
679b7619ce | |||
282233131a | |||
edf857bcb6 | |||
cd1d1e928a | |||
45d6421153 | |||
8c6f529b4b | |||
b23620b5ef | |||
e09e00fcd3 | |||
0d35d5834b | |||
ee8dc75be3 | |||
5f91be547e | |||
7439622cd6 |
3
.github/ISSUE_TEMPLATE/bug.md
vendored
3
.github/ISSUE_TEMPLATE/bug.md
vendored
@ -6,7 +6,7 @@ labels: bug
|
|||||||
---
|
---
|
||||||
|
|
||||||
警告: 在进一步操作之前,请检查下列选项。如果您忽视此模板或者没有提供关键信息,您的 Issue 将直接被关闭
|
警告: 在进一步操作之前,请检查下列选项。如果您忽视此模板或者没有提供关键信息,您的 Issue 将直接被关闭
|
||||||
- 确保您使用的是 [最新开发版本](https://github.com/whitechi73/Shamrock/actions/workflows/build-apk.yml) 的 Shamrock.
|
- 确保您使用的是 [最新开发版本](https://github.com/whitechi73/OpenShamrock/actions/workflows/build-apk.yml) 的 Shamrock.
|
||||||
- 确保您的问题尚未在 Issues 列表中提出.
|
- 确保您的问题尚未在 Issues 列表中提出.
|
||||||
- 确保您的问题不是由于您的代码错误导致的.
|
- 确保您的问题不是由于您的代码错误导致的.
|
||||||
|
|
||||||
@ -22,5 +22,6 @@ labels: bug
|
|||||||
|
|
||||||
- Shamrock 版本:
|
- Shamrock 版本:
|
||||||
- Android 版本:
|
- Android 版本:
|
||||||
|
- LSPosed 框架版本:
|
||||||
- 设备的制造商和型号:
|
- 设备的制造商和型号:
|
||||||
- 设备的 CPU 架构:
|
- 设备的 CPU 架构:
|
||||||
|
2
.github/ISSUE_TEMPLATE/feature.md
vendored
2
.github/ISSUE_TEMPLATE/feature.md
vendored
@ -7,7 +7,7 @@ labels: enhancement
|
|||||||
|
|
||||||
警告: 在进一步操作之前,请检查下列选项。如果您忽视此模板或者没有提供关键信息,您的 Issue 将直接被关闭
|
警告: 在进一步操作之前,请检查下列选项。如果您忽视此模板或者没有提供关键信息,您的 Issue 将直接被关闭
|
||||||
|
|
||||||
- 确保您使用的是 [最新开发版本](https://github.com/whitechi73/Shamrock/actions/workflows/build-apk.yml) 的 Shamrock.
|
- 确保您使用的是 [最新开发版本](https://github.com/whitechi73/OpenShamrock/actions/workflows/build-apk.yml) 的 Shamrock.
|
||||||
- 确保您的功能请求尚未在 Issues 列表中提出.
|
- 确保您的功能请求尚未在 Issues 列表中提出.
|
||||||
- 确保您的功能请求是与 Shamrock 相关的,且可以实现.
|
- 确保您的功能请求是与 Shamrock 相关的,且可以实现.
|
||||||
|
|
||||||
|
BIN
.github/jetbrains-variant-3.png
vendored
Normal file
BIN
.github/jetbrains-variant-3.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 178 KiB |
71
.github/workflows/build-apk.yml
vendored
71
.github/workflows/build-apk.yml
vendored
@ -13,24 +13,38 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build APK
|
name: Build Shamrock
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Setup JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
java-version: 17
|
java-version: 17
|
||||||
cache: 'gradle'
|
distribution: "adopt"
|
||||||
|
|
||||||
- name: Setup cmake
|
- name: Cache Gradle Dependencies
|
||||||
run: |
|
uses: actions/cache@v4
|
||||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "cmake;3.22.1" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
with:
|
||||||
echo "sdk.dir=${ANDROID_HOME}" > local.properties
|
path: |
|
||||||
|
~/.gradle/caches
|
||||||
|
~/.gradle/wrapper
|
||||||
|
!~/.gradle/caches/build-cache-*
|
||||||
|
key: gradle-deps-core-${{ hashFiles('**/build.gradle.kts') }}
|
||||||
|
restore-keys: gradle-deps
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: Cache Gradle Build
|
||||||
uses: gradle/gradle-build-action@v2.9.0
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.gradle/caches/build-cache-*
|
||||||
|
~/.gradle/buildOutputCleanup/cache.properties
|
||||||
|
key: gradle-builds-core-${{ github.sha }}
|
||||||
|
restore-keys: gradle-builds
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: |
|
run: |
|
||||||
@ -46,42 +60,41 @@ jobs:
|
|||||||
KEY_ALIAS: ${{ secrets.SIGN_ALIAS }}
|
KEY_ALIAS: ${{ secrets.SIGN_ALIAS }}
|
||||||
KEY_PASSWORD: ${{ secrets.SIGN_KEY_PASSWORD }}
|
KEY_PASSWORD: ${{ secrets.SIGN_KEY_PASSWORD }}
|
||||||
|
|
||||||
- name: Install aapt
|
|
||||||
run: sudo apt-get update && sudo apt-get install -y aapt
|
|
||||||
|
|
||||||
- name: Set Shamrock Version
|
- name: Set Shamrock Version
|
||||||
run: |
|
run: |
|
||||||
apk_file=${{ env.APK_FILE_ALL }}
|
version_name_all=$(basename -s .apk "${{ env.APK_FILE_ALL }}")
|
||||||
apk_dump=$(aapt dump badging "$apk_file")
|
version_name_arm64=$(basename -s .apk "${{ env.APK_FILE_ARM64 }}")
|
||||||
version_name=$(sed -n "s/.*versionName='\([^']*\)'.*/\1/p" <<< "$apk_dump")
|
version_name_x86_64=$(basename -s .apk "${{ env.APK_FILE_X86_64 }}")
|
||||||
echo "SHAMROCK_VERSION=$version_name" >> $GITHUB_ENV
|
echo "SHAMROCK_VERSION_ALL=$version_name_all" >> $GITHUB_ENV
|
||||||
|
echo "SHAMROCK_VERSION_ARM64=$version_name_arm64" >> $GITHUB_ENV
|
||||||
|
echo "SHAMROCK_VERSION_x86_64=$version_name_x86_64" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Show Artifacts SHA256
|
- name: Show Artifacts SHA256
|
||||||
run: |
|
run: |
|
||||||
echo "### Build Success :rocket:" >> $GITHUB_STEP_SUMMARY
|
echo "### Build Success :rocket:" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "|ABI|SHA256|" >> $GITHUB_STEP_SUMMARY
|
echo "|ABI|SHA256|" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "|:--------:|:----------|" >> $GITHUB_STEP_SUMMARY
|
echo "|:--------:|:----------|" >> $GITHUB_STEP_SUMMARY
|
||||||
all=($(sha256sum ${{ env.APK_FILE_ALL }}))
|
all=($(sha256sum "${{ env.APK_FILE_ALL }}"))
|
||||||
echo "|all|$all" >> $GITHUB_STEP_SUMMARY
|
echo "|all|$all" >> $GITHUB_STEP_SUMMARY
|
||||||
arm64=($(sha256sum ${{ env.APK_FILE_ARM64 }}))
|
arm64=($(sha256sum "${{ env.APK_FILE_ARM64 }}"))
|
||||||
echo "|arm64|$arm64" >> $GITHUB_STEP_SUMMARY
|
echo "|arm64|$arm64" >> $GITHUB_STEP_SUMMARY
|
||||||
x86_64=($(sha256sum ${{ env.APK_FILE_X86_64 }}))
|
x86_64=($(sha256sum "${{ env.APK_FILE_X86_64 }}"))
|
||||||
echo "|x86_64|$x86_64" >> $GITHUB_STEP_SUMMARY
|
echo "|x86_64|$x86_64" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
- name: Upload ALL APK RELEASE
|
- name: Upload ALL APK RELEASE
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Shamrock-v${{ env.SHAMROCK_VERSION }}-all
|
name: "${{ env.SHAMROCK_VERSION_ALL }}"
|
||||||
path: ${{ env.APK_FILE_ALL }}
|
path: "${{ env.APK_FILE_ALL }}"
|
||||||
|
|
||||||
- name: Upload ARM64 APK RELEASE
|
- name: Upload ARM64 APK RELEASE
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Shamrock-v${{ env.SHAMROCK_VERSION }}-arm64
|
name: "${{ env.SHAMROCK_VERSION_ARM64 }}"
|
||||||
path: ${{ env.APK_FILE_ARM64 }}
|
path: "${{ env.APK_FILE_ARM64 }}"
|
||||||
|
|
||||||
- name: Upload X86_64 APK RELEASE
|
- name: Upload X86_64 APK RELEASE
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Shamrock-v${{ env.SHAMROCK_VERSION }}-x86_64
|
name: "${{ env.SHAMROCK_VERSION_x86_64 }}"
|
||||||
path: ${{ env.APK_FILE_X86_64 }}
|
path: "${{ env.APK_FILE_X86_64 }}"
|
57
.github/workflows/codeql.yml
vendored
57
.github/workflows/codeql.yml
vendored
@ -1,57 +0,0 @@
|
|||||||
name: "CodeQL"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "master" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "master" ]
|
|
||||||
schedule:
|
|
||||||
- cron: '24 7 * * 4'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 360
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language: [ 'cpp', 'java' ]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3.6.0
|
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v2
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
|
|
||||||
- name: Setup JDK 17
|
|
||||||
uses: actions/setup-java@v3.12.0
|
|
||||||
with:
|
|
||||||
distribution: "temurin"
|
|
||||||
java-version: 17
|
|
||||||
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: gradle/gradle-build-action@v2.8.0
|
|
||||||
|
|
||||||
- name: Setup cmake
|
|
||||||
run: |
|
|
||||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "cmake;3.22.1" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
|
||||||
echo "sdk.dir=${ANDROID_HOME}" > local.properties
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
chmod +x ./gradlew
|
|
||||||
./gradlew :app:assembleAppRelease
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v2
|
|
||||||
with:
|
|
||||||
category: "/language:${{matrix.language}}"
|
|
73
.github/workflows/release.yml
vendored
73
.github/workflows/release.yml
vendored
@ -1,73 +0,0 @@
|
|||||||
name: Shamrock Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Release
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: "temurin"
|
|
||||||
java-version: 17
|
|
||||||
cache: 'gradle'
|
|
||||||
|
|
||||||
- name: Setup cmake
|
|
||||||
run: |
|
|
||||||
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "cmake;3.22.1" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
|
|
||||||
echo "sdk.dir=${ANDROID_HOME}" > local.properties
|
|
||||||
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: gradle/gradle-build-action@v2.9.0
|
|
||||||
|
|
||||||
- name: Build with Gradle
|
|
||||||
run: |
|
|
||||||
echo ${{ secrets.SIGN_KEYSTORE_BASE64 }} | base64 -d > keystore.jks
|
|
||||||
chmod +x ./gradlew
|
|
||||||
./gradlew :app:assembleRelease --build-cache --parallel --daemon --warning-mode all --stacktrace
|
|
||||||
echo "APK_FILE_ALL=$(find app/build/outputs/apk/app/release -name '*.apk')" >> $GITHUB_ENV
|
|
||||||
echo "APK_FILE_ARM64=$(find app/build/outputs/apk/arm64/release -name '*.apk')" >> $GITHUB_ENV
|
|
||||||
echo "APK_FILE_X86_64=$(find app/build/outputs/apk/x64/release -name '*.apk')" >> $GITHUB_ENV
|
|
||||||
env:
|
|
||||||
KEYSTORE_PATH: "../keystore.jks"
|
|
||||||
KEYSTORE_PASSWORD: ${{ secrets.SIGN_KEYSTORE_PASSWORD }}
|
|
||||||
KEY_ALIAS: ${{ secrets.SIGN_ALIAS }}
|
|
||||||
KEY_PASSWORD: ${{ secrets.SIGN_KEY_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Install aapt
|
|
||||||
run: sudo apt-get update && sudo apt-get install -y aapt
|
|
||||||
|
|
||||||
- name: Set Shamrock Version
|
|
||||||
run: |
|
|
||||||
apk_file=${{ env.APK_FILE_ALL }}
|
|
||||||
apk_dump=$(aapt dump badging "$apk_file")
|
|
||||||
version_name=$(sed -n "s/.*versionName='\([^']*\)'.*/\1/p" <<< "$apk_dump")
|
|
||||||
echo "SHAMROCK_VERSION=$version_name" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Show Artifacts SHA256
|
|
||||||
run: |
|
|
||||||
echo "### Build Success :rocket:" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "|ABI|SHA256|" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "|:--------:|:----------|" >> $GITHUB_STEP_SUMMARY
|
|
||||||
all=($(sha256sum ${{ env.APK_FILE_ALL }}))
|
|
||||||
echo "|all|$all" >> $GITHUB_STEP_SUMMARY
|
|
||||||
arm64=($(sha256sum ${{ env.APK_FILE_ARM64 }}))
|
|
||||||
echo "|arm64|$arm64" >> $GITHUB_STEP_SUMMARY
|
|
||||||
x86_64=($(sha256sum ${{ env.APK_FILE_X86_64 }}))
|
|
||||||
echo "|x86_64|$x86_64" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
- name: Release
|
|
||||||
uses: marvinpinto/action-automatic-releases@latest
|
|
||||||
with:
|
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
automatic_release_tag: Shamrock v${{ env.SHAMROCK_VERSION }}
|
|
||||||
files: |
|
|
||||||
${{ env.APK_FILE_ALL }}
|
|
||||||
${{ env.APK_FILE_ARM64 }}
|
|
||||||
${{ env.APK_FILE_X86_64 }}
|
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "kritor"]
|
||||||
|
path = kritor/kritor
|
||||||
|
url = https://github.com/KarinJS/kritor
|
40
README.md
40
README.md
@ -10,26 +10,41 @@
|
|||||||
![][onebot-12]
|
![][onebot-12]
|
||||||
[![][license]](LICENSE)
|
[![][license]](LICENSE)
|
||||||
|
|
||||||
[下载][download-link] | [部署][deploy-link] | [接口][api-link] | [文档][docs-link] | [加群][group-link]
|
[下载][download-link] | [部署][deploy-link] | [接口][api-link] | [文档][docs-link]
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 简介
|
## 简介
|
||||||
|
|
||||||
☘ 基于 Xposed 实现 OneBot 标准的 QQ 机器人框架,原作者[**fuqiuluo**](https://github.com/fuqiuluo)已脱离开发,接下来由白池接手哦!本项目为OpenShamrock,不会有任何收费行为,欢迎大家的加入!
|
☘ 基于 Lsposed(**Non**-Riru) 实现 Kritor 标准的 QQ 机器人框架!
|
||||||
|
|
||||||
> 本项目仅提供学习与交流用途,请在24小时内删除。
|
> 本项目仅提供学习与交流用途,请在24小时内删除。
|
||||||
> 本项目目的是研究 Xposed 和 LSPosed 框架的使用。 Epic 框架开发相关知识。
|
> 本项目目的是研究 Xposed 和 LSPosed 框架的使用。 Epic 框架开发相关知识。
|
||||||
|
> Riru可能导致封禁,请减少使用。
|
||||||
> 如有违反法律,请联系删除。
|
> 如有违反法律,请联系删除。
|
||||||
> 请勿在任何平台宣传,宣扬,转发本项目,请勿恶意修改企业安装包造成相关企业产生损失,如有违背,必将追责到底。
|
> 请勿在任何平台宣传,宣扬,转发本项目,请勿恶意修改企业安装包造成相关企业产生损失,如有违背,必将追责到底。
|
||||||
> 官方论坛,[点我直达](https://forum.libfekit.so/)!
|
|
||||||
|
|
||||||
## 兼容|迁移|替代 说明
|
## 兼容|迁移|替代 说明
|
||||||
|
|
||||||
- 一键移植:本项目基于 go-cqhttp 的文档进行开发实现。
|
- 一键移植:本项目基于 go-cqhttp 的文档进行开发实现。
|
||||||
- 平行部署:可多平台部署,未来将会支持 Docker 部署的教程。
|
- 平行部署:可多平台部署。
|
||||||
|
|
||||||
> 若您追求小而轻便的Bot服务, [Chronocat](https://chronocat.vercel.app/)是您的不二之选。
|
## 相关项目
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><a href="https://github.com/LagrangeDev/Lagrange.Core">Lagrange.Core</a></td>
|
||||||
|
<td>NTQQ 的协议实现</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="https://github.com/whitechi73/OpenShamrock">OpenShamrock</a></td>
|
||||||
|
<td>基于 Xposed 实现 OneBot 标准的机器人框架(👈你在这里</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="https://github.com/chrononeko/chronocat">Chronocat</a></td>
|
||||||
|
<td>基于 Electron 的、模块化的 Satori 框架</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
## 权限声明
|
## 权限声明
|
||||||
|
|
||||||
@ -45,7 +60,13 @@
|
|||||||
|
|
||||||
## 贡献说明
|
## 贡献说明
|
||||||
|
|
||||||
<img src="https://github.com/whitechi73/OpenShamrock/assets/98259561/f04d60bc-ec40-41fc-bc15-62c146f1a1f1" width="160px"> **我可爱吗?欢迎你的到来,这里是一个很大的地方,有着无限可能,主要是有你啦!**
|
<img src="https://github.com/whitechi73/OpenShamrock/assets/98259561/f04d60bc-ec40-41fc-bc15-62c146f1a1f1" width="160px" alt="Shamrock"> **我可爱吗?欢迎你的到来,这里是一个很大的地方,有着无限可能,主要是有你啦!**
|
||||||
|
|
||||||
|
## 鸣谢
|
||||||
|
|
||||||
|
感谢[**JetBrains**](https://www.jetbrains.com/zh-cn/community/opensource/#support)提供的开源开发许可证,JetBrains 通过为核心项目贡献者免费提供一套一流的开发者工具来支持非商业开源项目。
|
||||||
|
|
||||||
|
[<img src=".github/jetbrains-variant-3.png" width="200"/>](https://www.jetbrains.com/zh-cn/community/opensource/#support)
|
||||||
|
|
||||||
## 开源协议
|
## 开源协议
|
||||||
|
|
||||||
@ -53,7 +74,7 @@
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
Shamrock - OneBot standard QQ robot framework based on Xposed implementation
|
Shamrock - OneBot standard QQ robot framework based on Xposed implementation
|
||||||
Copyright (C) 2023 Shamrock Team
|
Copyright (C) 2023 ~ 2024 Shamrock Team
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
@ -96,12 +117,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
[docs-link]: https://whitechi73.github.io/OpenShamrock/
|
[docs-link]: https://whitechi73.github.io/OpenShamrock/
|
||||||
|
|
||||||
[group-link]: https://whitechi73.github.io/OpenShamrock/group.html
|
[hook-system]: https://github.com/whitechi73/OpenShamrock/blob/master/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/KeepAlive.kt
|
||||||
|
|
||||||
[hook-system]: https://github.com/whitechi73/OpenShamrock/wiki/perm_hook_android
|
|
||||||
|
|
||||||
[voice-support]: https://whitechi73.github.io/OpenShamrock/advanced/voice.html
|
[voice-support]: https://whitechi73.github.io/OpenShamrock/advanced/voice.html
|
||||||
|
|
||||||
[contrib-image]: https://contrib.rocks/image?repo=whitechi73/OpenShamrock
|
[contrib-image]: https://contrib.rocks/image?repo=whitechi73/OpenShamrock
|
||||||
|
|
||||||
[contrib-link]: https://github.com/whitechi73/OpenShamrock/graphs/contributors
|
[contrib-link]: https://github.com/whitechi73/OpenShamrock/graphs/contributors
|
||||||
|
|
||||||
|
12
SECURITY.md
12
SECURITY.md
@ -1,11 +1,19 @@
|
|||||||
# Security Policy
|
# Security Policy
|
||||||
|
|
||||||
## Support Version
|
## 支持的版本
|
||||||
|
|
||||||
| Version | Supported |
|
| 版本 | 支持状态 |
|
||||||
| ------- | ------------------ |
|
| ------- | ------------------ |
|
||||||
|
| 9.0.15 | :white_check_mark: |
|
||||||
| 8.9.75 | :white_check_mark: |
|
| 8.9.75 | :white_check_mark: |
|
||||||
| 8.9.73 | :white_check_mark: |
|
| 8.9.73 | :white_check_mark: |
|
||||||
| 8.9.98 | :white_check_mark: |
|
| 8.9.98 | :white_check_mark: |
|
||||||
| < 8.9.68| :x: |
|
| < 8.9.68| :x: |
|
||||||
|
|
||||||
|
## 频道支持性说明
|
||||||
|
|
||||||
|
如果需要使用`频道`相关功能,请升级QQ到9.0.8版本!
|
||||||
|
|
||||||
|
## Riru检测问题
|
||||||
|
|
||||||
|
QQ自`9.0.8`开始将会检测riru,可能作为封号因素。
|
||||||
|
1
annotations/.gitignore
vendored
Normal file
1
annotations/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build
|
14
annotations/build.gradle.kts
Normal file
14
annotations/build.gradle.kts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
plugins {
|
||||||
|
id("java-library")
|
||||||
|
id("org.jetbrains.kotlin.jvm")
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
//implementation(DEPENDENCY_PROTOBUF)
|
||||||
|
implementation(kotlinx("serialization-protobuf", "1.6.2"))
|
||||||
|
}
|
9
annotations/src/main/java/kritor/service/Grpc.kt
Normal file
9
annotations/src/main/java/kritor/service/Grpc.kt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package kritor.service
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
@Target(AnnotationTarget.FUNCTION)
|
||||||
|
annotation class Grpc(
|
||||||
|
val serviceName: String,
|
||||||
|
val funcName: String,
|
||||||
|
|
||||||
|
)
|
14
annotations/src/main/java/moe/fuqiuluo/symbols/Protobuf.kt
Normal file
14
annotations/src/main/java/moe/fuqiuluo/symbols/Protobuf.kt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package moe.fuqiuluo.symbols
|
||||||
|
|
||||||
|
import kotlinx.serialization.decodeFromByteArray
|
||||||
|
import kotlinx.serialization.protobuf.ProtoBuf
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
val EMPTY_BYTE_ARRAY = ByteArray(0)
|
||||||
|
|
||||||
|
interface Protobuf<T: Protobuf<T>>
|
||||||
|
|
||||||
|
inline fun <reified T: Protobuf<T>> ByteArray.decodeProtobuf(to: KClass<T>? = null): T {
|
||||||
|
return ProtoBuf.decodeFromByteArray(this)
|
||||||
|
}
|
13
annotations/src/main/java/moe/fuqiuluo/symbols/XposedHook.kt
Normal file
13
annotations/src/main/java/moe/fuqiuluo/symbols/XposedHook.kt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package moe.fuqiuluo.symbols
|
||||||
|
|
||||||
|
enum class Process {
|
||||||
|
ALL,
|
||||||
|
MAIN,
|
||||||
|
MSF
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
annotation class XposedHook(
|
||||||
|
val process: Process = Process.ALL,
|
||||||
|
val priority: Int = 10
|
||||||
|
)
|
@ -1,35 +1,29 @@
|
|||||||
import com.android.build.api.dsl.ApplicationExtension
|
import com.android.build.api.dsl.ApplicationExtension
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
fun gitCommitHash(): String {
|
|
||||||
val builder = ProcessBuilder("git", "rev-parse", "--short", "HEAD")
|
|
||||||
val process = builder.start()
|
|
||||||
val reader = process.inputReader()
|
|
||||||
val hash = reader.readText().trim()
|
|
||||||
return if (hash.isNotEmpty()) ".$hash" else ""
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("org.jetbrains.kotlin.android")
|
id("org.jetbrains.kotlin.android")
|
||||||
kotlin("plugin.serialization") version "1.8.10"
|
kotlin("plugin.serialization") version "1.9.22"
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "moe.fuqiuluo.shamrock"
|
namespace = "moe.fuqiuluo.shamrock"
|
||||||
ndkVersion = "25.1.8937393"
|
ndkVersion = "25.1.8937393"
|
||||||
compileSdk = 33
|
compileSdk = 34
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "moe.fuqiuluo.shamrock"
|
applicationId = "moe.fuqiuluo.shamrock"
|
||||||
minSdk = 24
|
minSdk = 27
|
||||||
targetSdk = 33
|
targetSdk = 34
|
||||||
versionCode = (System.currentTimeMillis() / 1000).toInt()
|
versionCode = getVersionCode()
|
||||||
versionName = "1.0.6-dev" + gitCommitHash()
|
versionName = "1.1.0" + ".r${getGitCommitCount()}." + getVersionName()
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
useSupportLibrary = true
|
useSupportLibrary = true
|
||||||
}
|
}
|
||||||
|
@Suppress("UnstableApiUsage")
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
cppFlags += ""
|
cppFlags += ""
|
||||||
@ -50,8 +44,7 @@ android {
|
|||||||
android.applicationVariants.all {
|
android.applicationVariants.all {
|
||||||
outputs.map { it as com.android.build.gradle.internal.api.BaseVariantOutputImpl }
|
outputs.map { it as com.android.build.gradle.internal.api.BaseVariantOutputImpl }
|
||||||
.forEach {
|
.forEach {
|
||||||
val abi = it.outputFileName.split("-")[1].split(".apk")[0]
|
val abiName = when (val abi = it.outputFileName.split("-")[1].split(".apk")[0]) {
|
||||||
val abiName = when (abi) {
|
|
||||||
"app" -> "all"
|
"app" -> "all"
|
||||||
"x64" -> "x86_64"
|
"x64" -> "x86_64"
|
||||||
else -> abi
|
else -> abi
|
||||||
@ -69,6 +62,7 @@ android {
|
|||||||
println("Full architecture and full compilation.")
|
println("Full architecture and full compilation.")
|
||||||
abiFilters.add("arm64-v8a")
|
abiFilters.add("arm64-v8a")
|
||||||
abiFilters.add("x86_64")
|
abiFilters.add("x86_64")
|
||||||
|
abiFilters.add("x86")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
create("arm64") {
|
create("arm64") {
|
||||||
@ -98,7 +92,7 @@ android {
|
|||||||
compose = true
|
compose = true
|
||||||
}
|
}
|
||||||
composeOptions {
|
composeOptions {
|
||||||
kotlinCompilerExtensionVersion = "1.4.3"
|
kotlinCompilerExtensionVersion = "1.5.10"
|
||||||
}
|
}
|
||||||
packaging {
|
packaging {
|
||||||
jniLibs {
|
jniLibs {
|
||||||
@ -154,15 +148,47 @@ fun configureAppSigningConfigsForRelease(project: Project) {
|
|||||||
release {
|
release {
|
||||||
signingConfig = signingConfigs.findByName("release")
|
signingConfig = signingConfigs.findByName("release")
|
||||||
}
|
}
|
||||||
|
debug {
|
||||||
|
signingConfig = signingConfigs.findByName("release")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getGitCommitCount(): Int {
|
||||||
|
val out = ByteArrayOutputStream()
|
||||||
|
exec {
|
||||||
|
commandLine("git", "rev-list", "--count", "HEAD")
|
||||||
|
standardOutput = out
|
||||||
|
}
|
||||||
|
return out.toString().trim().toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getGitCommitHash(): String {
|
||||||
|
val out = ByteArrayOutputStream()
|
||||||
|
exec {
|
||||||
|
commandLine("git", "rev-parse", "--short", "HEAD")
|
||||||
|
standardOutput = out
|
||||||
|
}
|
||||||
|
return out.toString().trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getVersionCode(): Int {
|
||||||
|
return (System.currentTimeMillis() / 1000L).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getVersionName(): String {
|
||||||
|
return getGitCommitHash()
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("androidx.core:core-ktx:1.9.0")
|
val composeBom = platform("androidx.compose:compose-bom:2023.10.01")
|
||||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")
|
implementation(composeBom)
|
||||||
implementation("androidx.activity:activity-compose:1.7.2")
|
|
||||||
implementation(platform("androidx.compose:compose-bom:2023.06.01"))
|
DEPENDENCY_ANDROIDX.forEach {
|
||||||
|
implementation(it)
|
||||||
|
}
|
||||||
|
|
||||||
implementation("androidx.compose.ui:ui")
|
implementation("androidx.compose.ui:ui")
|
||||||
implementation("androidx.compose.ui:ui-graphics")
|
implementation("androidx.compose.ui:ui-graphics")
|
||||||
implementation("androidx.compose.ui:ui-tooling-preview")
|
implementation("androidx.compose.ui:ui-tooling-preview")
|
||||||
@ -171,31 +197,20 @@ dependencies {
|
|||||||
implementation("com.google.accompanist:accompanist-pager:0.31.5+")
|
implementation("com.google.accompanist:accompanist-pager:0.31.5+")
|
||||||
//noinspection GradleDynamicVersion
|
//noinspection GradleDynamicVersion
|
||||||
implementation("com.google.accompanist:accompanist-systemuicontroller:0.31.5+")
|
implementation("com.google.accompanist:accompanist-systemuicontroller:0.31.5+")
|
||||||
//noinspection GradleDynamicVersion useless
|
|
||||||
// implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0+")
|
|
||||||
implementation("io.coil-kt:coil:2.4.0")
|
implementation("io.coil-kt:coil:2.4.0")
|
||||||
implementation("io.coil-kt:coil-compose:2.4.0")
|
implementation("io.coil-kt:coil-compose:2.4.0")
|
||||||
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.1.16")
|
implementation(kotlinx("io-jvm", "0.1.16"))
|
||||||
|
implementation(ktor("client", "core"))
|
||||||
val ktorVersion = "2.3.3"
|
implementation(ktor("client", "okhttp"))
|
||||||
implementation("io.ktor:ktor-server-core:$ktorVersion")
|
implementation(ktor("serialization", "kotlinx-json"))
|
||||||
implementation("io.ktor:ktor-server-host-common:$ktorVersion")
|
|
||||||
implementation("io.ktor:ktor-server-status-pages:$ktorVersion")
|
|
||||||
implementation("io.ktor:ktor-server-netty:$ktorVersion")
|
|
||||||
implementation("io.ktor:ktor-server-content-negotiation:$ktorVersion")
|
|
||||||
implementation("io.ktor:ktor-client-core:$ktorVersion")
|
|
||||||
implementation("io.ktor:ktor-client-cio:$ktorVersion")
|
|
||||||
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
|
|
||||||
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
|
|
||||||
//implementation("io.ktor:ktor-serialization-kotlinx-protobuf:$ktorVersion")
|
|
||||||
|
|
||||||
implementation(project(":xposed"))
|
implementation(project(":xposed"))
|
||||||
|
|
||||||
testImplementation("junit:junit:4.13.2")
|
testImplementation("junit:junit:4.13.2")
|
||||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||||
androidTestImplementation(platform("androidx.compose:compose-bom:2023.06.01"))
|
androidTestImplementation(platform("androidx.compose:compose-bom:2023.10.01"))
|
||||||
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
||||||
debugImplementation("androidx.compose.ui:ui-tooling")
|
debugImplementation("androidx.compose.ui:ui-tooling")
|
||||||
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
||||||
|
21
app/proguard-rules.pro
vendored
21
app/proguard-rules.pro
vendored
@ -199,17 +199,36 @@
|
|||||||
|
|
||||||
-keep class com.arthenica.ffmpegkit.NativeLoader { *; }
|
-keep class com.arthenica.ffmpegkit.NativeLoader { *; }
|
||||||
|
|
||||||
-keep class moe.fuqiuluo.** { *; }
|
-keep class moe.fuqiuluo.shamrock.app.** { *; }
|
||||||
|
-keep class moe.fuqiuluo.shamrock.ui.** { *; }
|
||||||
|
-keep class moe.fuqiuluo.shamrock.MainActivity { *; }
|
||||||
|
-keep class moe.fuqiuluo.shamrock.MainActivityKt { *; }
|
||||||
|
-keep class moe.fuqiuluo.shamrock.Manifest { *; }
|
||||||
|
|
||||||
|
-keep class moe.fuqiuluo.shamrock.xposed.** { *; }
|
||||||
|
-keep class moe.fuqiuluo.shamrock.helper.** { *; }
|
||||||
|
|
||||||
|
# tencent interfaces rules
|
||||||
-keep class com.tencent.** { *; }
|
-keep class com.tencent.** { *; }
|
||||||
-keep class com.qq.** { *; }
|
-keep class com.qq.** { *; }
|
||||||
-keep class com.google.gson.** { *; }
|
-keep class com.google.gson.** { *; }
|
||||||
-keep class de.** { *; }
|
-keep class de.** { *; }
|
||||||
|
-keep class epic.** { *; }
|
||||||
|
-keep class friendlist.** { *; }
|
||||||
|
-keep class KQQ.** { *; }
|
||||||
-keep class mqq.** { *; }
|
-keep class mqq.** { *; }
|
||||||
|
-keep class msf.** { *; }
|
||||||
|
-keep class oicq.** { *; }
|
||||||
-keep class QQService.** { *; }
|
-keep class QQService.** { *; }
|
||||||
-keep class SummaryCard.** { *; }
|
-keep class SummaryCard.** { *; }
|
||||||
-keep class tencent.** { *; }
|
-keep class tencent.** { *; }
|
||||||
|
-keep class VIP.** { *; }
|
||||||
|
|
||||||
-keepclassmembers class * {
|
-keepclassmembers class * {
|
||||||
native <methods>;
|
native <methods>;
|
||||||
}
|
}
|
||||||
-keep class io.netty.** { *; }
|
-keep class io.netty.** { *; }
|
||||||
|
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
native <methods>;
|
||||||
|
}
|
||||||
|
@ -3,10 +3,6 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".app.MyApplication"
|
android:name=".app.MyApplication"
|
||||||
@ -18,6 +14,7 @@
|
|||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.Shamrock"
|
android:theme="@style/Theme.Shamrock"
|
||||||
android:zygotePreloadName="@string/app_name"
|
android:zygotePreloadName="@string/app_name"
|
||||||
|
android:multiArch="true"
|
||||||
tools:targetApi="31">
|
tools:targetApi="31">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
@ -34,7 +31,7 @@
|
|||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".ui.service.internal.MultifunctionalProvider"
|
android:name=".ui.service.internal.MultifunctionalProvider"
|
||||||
android:authorities="moe.fuqiuluo.xqbot.provider"
|
android:authorities="moe.fuqiuluo.108.provider"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:grantUriPermissions="true"
|
android:grantUriPermissions="true"
|
||||||
tools:ignore="ExportedContentProvider" />
|
tools:ignore="ExportedContentProvider" />
|
||||||
@ -47,7 +44,7 @@
|
|||||||
android:value="基于 Xposed 实现 OneBot 标准的 QQ 机器人框架" />
|
android:value="基于 Xposed 实现 OneBot 标准的 QQ 机器人框架" />
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="xposedminversion"
|
android:name="xposedminversion"
|
||||||
android:value="23" />
|
android:value="93" />
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="xposedscope"
|
android:name="xposedscope"
|
||||||
android:resource="@array/xposed_scope" />
|
android:resource="@array/xposed_scope" />
|
||||||
|
@ -37,9 +37,7 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
|
|||||||
# List C/C++ source files with relative paths to this CMakeLists.txt.
|
# List C/C++ source files with relative paths to this CMakeLists.txt.
|
||||||
${SRC_DIR}
|
${SRC_DIR}
|
||||||
md5.cpp
|
md5.cpp
|
||||||
cqcode.cpp
|
|
||||||
silk.cpp
|
silk.cpp
|
||||||
group_honor.cpp
|
|
||||||
message.cpp
|
message.cpp
|
||||||
shamrock.cpp)
|
shamrock.cpp)
|
||||||
|
|
||||||
|
@ -1,123 +0,0 @@
|
|||||||
#include <stdexcept>
|
|
||||||
#include "cqcode.h"
|
|
||||||
|
|
||||||
inline void replace_string(std::string& str, const std::string& from, const std::string& to) {
|
|
||||||
size_t startPos = 0;
|
|
||||||
while ((startPos = str.find(from, startPos)) != std::string::npos) {
|
|
||||||
str.replace(startPos, from.length(), to);
|
|
||||||
startPos += to.length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void decode_cqcode(const std::string& code, std::vector<std::unordered_map<std::string, std::string>>& dest) {
|
|
||||||
std::string cache;
|
|
||||||
bool is_start = false;
|
|
||||||
std::string key_tmp;
|
|
||||||
std::unordered_map<std::string, std::string> kv;
|
|
||||||
for(int i = 0; i < code.size(); i++) {
|
|
||||||
auto c = code[i];
|
|
||||||
if (c == '[') {
|
|
||||||
if (is_start) {
|
|
||||||
throw illegal_code();
|
|
||||||
} else {
|
|
||||||
if (!cache.empty()) {
|
|
||||||
std::unordered_map<std::string, std::string> kv;
|
|
||||||
kv.emplace("_type", "text");
|
|
||||||
kv.emplace("text", cache);
|
|
||||||
dest.push_back(kv);
|
|
||||||
cache.clear();
|
|
||||||
}
|
|
||||||
auto c1 = code[i + 1];
|
|
||||||
if (c1 == 'C') {
|
|
||||||
i++;
|
|
||||||
auto c2 = code[i + 1];
|
|
||||||
if(c2 == 'Q') {
|
|
||||||
i++;
|
|
||||||
auto c3 = code[i + 1];
|
|
||||||
if (c3 == ':') {
|
|
||||||
i++;
|
|
||||||
is_start = true;
|
|
||||||
} else {
|
|
||||||
cache += c;
|
|
||||||
cache += c1;
|
|
||||||
cache += c2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cache += c;
|
|
||||||
cache += c1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cache += c;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (c == '=') {
|
|
||||||
if (is_start) {
|
|
||||||
if (cache.empty()) {
|
|
||||||
throw illegal_code();
|
|
||||||
} else {
|
|
||||||
if (key_tmp.empty()) {
|
|
||||||
key_tmp.append(cache);
|
|
||||||
cache.clear();
|
|
||||||
} else {
|
|
||||||
cache += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cache += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (c == ',') {
|
|
||||||
if (is_start) {
|
|
||||||
if (kv.count("_type") == 0 && !cache.empty()) {
|
|
||||||
kv.emplace("_type", cache);
|
|
||||||
cache.clear();
|
|
||||||
} else {
|
|
||||||
if (!key_tmp.empty()) {
|
|
||||||
replace_string(cache, "&", "&");
|
|
||||||
replace_string(cache, "[", "[");
|
|
||||||
replace_string(cache, "]", "]");
|
|
||||||
replace_string(cache, ",", ",");
|
|
||||||
kv.emplace(key_tmp, cache);
|
|
||||||
cache.clear();
|
|
||||||
key_tmp.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cache += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (c == ']') {
|
|
||||||
if (is_start) {
|
|
||||||
if (!cache.empty()) {
|
|
||||||
if (!key_tmp.empty()) {
|
|
||||||
replace_string(cache, "&", "&");
|
|
||||||
replace_string(cache, "[", "[");
|
|
||||||
replace_string(cache, "]", "]");
|
|
||||||
replace_string(cache, ",", ",");
|
|
||||||
kv.emplace(key_tmp, cache);
|
|
||||||
}
|
|
||||||
dest.push_back(kv);
|
|
||||||
kv.clear();
|
|
||||||
key_tmp.clear();
|
|
||||||
cache.clear();
|
|
||||||
is_start = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cache += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cache += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!cache.empty()) {
|
|
||||||
std::unordered_map<std::string, std::string> kv;
|
|
||||||
kv.emplace("_type", "text");
|
|
||||||
kv.emplace("text", cache);
|
|
||||||
dest.push_back(kv);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
#include "jni.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
struct Honor {
|
|
||||||
int id;
|
|
||||||
std::string name;
|
|
||||||
std::string icon_url;
|
|
||||||
int priority;
|
|
||||||
};
|
|
||||||
|
|
||||||
int calc_honor_flag(int honor_id, char honor_flag);
|
|
||||||
|
|
||||||
jobject make_honor_object(JNIEnv *env, jobject user_id, const Honor& honor);
|
|
||||||
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
JNIEXPORT jobject JNICALL
|
|
||||||
Java_moe_fuqiuluo_shamrock_remote_action_handlers_GetTroopHonor_nativeDecodeHonor(JNIEnv *env, jobject thiz,
|
|
||||||
jstring user_id,
|
|
||||||
jint honor_id,
|
|
||||||
jbyte honor_flag) {
|
|
||||||
static std::vector<Honor> honor_list = {
|
|
||||||
Honor{1, "龙王", "https://qzonestyle.gtimg.cn/aoi/sola/20200213150116_n4PxCiurbm.png", 1},
|
|
||||||
Honor{2, "群聊之火", "https://qzonestyle.gtimg.cn/aoi/sola/20200217190136_92JEGFKC5k.png", 3},
|
|
||||||
Honor{3, "群聊炽焰", "https://qzonestyle.gtimg.cn/aoi/sola/20200217190204_zgCTeSrMq1.png", 4},
|
|
||||||
Honor{5, "冒尖小春笋", "https://qzonestyle.gtimg.cn/aoi/sola/20200213150335_tUJCAtoKVP.png", 5},
|
|
||||||
Honor{6, "快乐源泉", "https://qzonestyle.gtimg.cn/aoi/sola/20200213150434_3tDmsJExCP.png", 7},
|
|
||||||
Honor{7, "学术新星", "https://sola.gtimg.cn/aoi/sola/20200515140645_j0X6gbuHNP.png", 8},
|
|
||||||
Honor{8, "顶尖学霸", "https://sola.gtimg.cn/aoi/sola/20200515140639_0CtWOpfVzK.png", 9},
|
|
||||||
Honor{9, "至尊学神", "https://sola.gtimg.cn/aoi/sola/20200515140628_P8UEYBjMBT.png", 10},
|
|
||||||
Honor{10, "一笔当先", "https://sola.gtimg.cn/aoi/sola/20200515140654_4r94tSCdaB.png", 11},
|
|
||||||
Honor{11, "奋进小翠竹", "https://sola.gtimg.cn/aoi/sola/20200812151819_wbj6z2NGoB.png", 6},
|
|
||||||
Honor{12, "氛围魔杖", "https://sola.gtimg.cn/aoi/sola/20200812151831_4ZJgQCaD1H.png", 2},
|
|
||||||
Honor{13, "壕礼皇冠", "https://sola.gtimg.cn/aoi/sola/20200930154050_juZOAMg7pt.png", 12},
|
|
||||||
};
|
|
||||||
int flag = calc_honor_flag(honor_id, honor_flag);
|
|
||||||
if ((honor_id != 1 && honor_id != 2 && honor_id != 3) || flag != 1) {
|
|
||||||
auto honor = *std::find_if(honor_list.begin(), honor_list.end(), [&honor_id](auto &honor) {
|
|
||||||
return honor.id == honor_id;
|
|
||||||
});
|
|
||||||
return make_honor_object(env, user_id, honor);
|
|
||||||
} else {
|
|
||||||
auto honor = *std::find_if(honor_list.begin(), honor_list.end(), [&honor_id](auto &honor) {
|
|
||||||
return honor.id == honor_id;
|
|
||||||
});
|
|
||||||
std::string url = "https://static-res.qq.com/static-res/groupInteract/vas/a/" + std::to_string(honor_id) + "_1.png";
|
|
||||||
honor = Honor{honor_id, honor.name, url, honor.priority};
|
|
||||||
return make_honor_object(env, user_id, honor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int calc_honor_flag(int honor_id, char honor_flag) {
|
|
||||||
int flag;
|
|
||||||
if (honor_flag == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (honor_id == 1) {
|
|
||||||
flag = honor_flag;
|
|
||||||
} else if (honor_id == 2 || honor_id == 3) {
|
|
||||||
flag = honor_flag >> 2;
|
|
||||||
} else if (honor_id != 4) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
flag = honor_flag >> 4;
|
|
||||||
}
|
|
||||||
return flag & 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
jobject make_honor_object(JNIEnv *env, jobject user_id, const Honor& honor) {
|
|
||||||
jclass GroupMemberHonor = env->FindClass("moe/fuqiuluo/shamrock/remote/service/data/GroupMemberHonor");
|
|
||||||
jmethodID GroupMemberHonor_init = env->GetMethodID(GroupMemberHonor, "<init>",
|
|
||||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
|
|
||||||
auto user_id_str = (jstring) user_id;
|
|
||||||
jstring honor_desc = env->NewStringUTF(honor.name.c_str());
|
|
||||||
jstring uin_name = env->NewStringUTF("");
|
|
||||||
jstring honor_icon_url = env->NewStringUTF(honor.icon_url.c_str());
|
|
||||||
jobject ret = env->NewObject(GroupMemberHonor, GroupMemberHonor_init, user_id_str, uin_name, honor_icon_url, 0, honor.id, honor_desc);
|
|
||||||
|
|
||||||
env->DeleteLocalRef(GroupMemberHonor);
|
|
||||||
env->DeleteLocalRef(user_id_str);
|
|
||||||
env->DeleteLocalRef(honor_desc);
|
|
||||||
env->DeleteLocalRef(honor_icon_url);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
#ifndef UNTITLED_CQCODE_H
|
|
||||||
#define UNTITLED_CQCODE_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
class illegal_code: std::exception {
|
|
||||||
public:
|
|
||||||
[[nodiscard]] const char * what() const noexcept override {
|
|
||||||
return "Error cq code.";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void decode_cqcode(const std::string& code, std::vector<std::unordered_map<std::string, std::string>>& dest);
|
|
||||||
|
|
||||||
void encode_cqcode(const std::vector<std::unordered_map<std::string, std::string>>& segment, std::string& dest);
|
|
||||||
|
|
||||||
#endif //UNTITLED_CQCODE_H
|
|
@ -1,5 +1,4 @@
|
|||||||
#include "jni.h"
|
#include "jni.h"
|
||||||
#include "cqcode.h"
|
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
inline void replace_string(std::string& str, const std::string& from, const std::string& to) {
|
inline void replace_string(std::string& str, const std::string& from, const std::string& to) {
|
||||||
@ -12,7 +11,7 @@ inline void replace_string(std::string& str, const std::string& from, const std:
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jlong JNICALL
|
JNIEXPORT jlong JNICALL
|
||||||
Java_moe_fuqiuluo_shamrock_helper_MessageHelper_createMessageUniseq(JNIEnv *env, jobject thiz,
|
Java_qq_service_msg_MessageHelper_createMessageUniseq(JNIEnv *env, jobject thiz,
|
||||||
jint chat_type,
|
jint chat_type,
|
||||||
jlong time) {
|
jlong time) {
|
||||||
static std::random_device rd;
|
static std::random_device rd;
|
||||||
@ -32,123 +31,6 @@ Java_moe_fuqiuluo_shamrock_helper_MessageHelper_getChatType(JNIEnv *env, jobject
|
|||||||
return (int32_t) ((int64_t) msg_id & 0xffL);
|
return (int32_t) ((int64_t) msg_id & 0xffL);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
JNIEXPORT jobject JNICALL
|
|
||||||
Java_moe_fuqiuluo_shamrock_helper_MessageHelper_nativeDecodeCQCode(JNIEnv *env, jobject thiz,
|
|
||||||
jstring code) {
|
|
||||||
jclass ArrayList = env->FindClass("java/util/ArrayList");
|
|
||||||
jmethodID NewArrayList = env->GetMethodID(ArrayList, "<init>", "()V");
|
|
||||||
jmethodID ArrayListAdd = env->GetMethodID(ArrayList, "add", "(Ljava/lang/Object;)Z");
|
|
||||||
jobject arrayList = env->NewObject(ArrayList, NewArrayList);
|
|
||||||
|
|
||||||
const char* cCode = env->GetStringUTFChars(code, nullptr);
|
|
||||||
std::string cppCode = cCode;
|
|
||||||
std::vector<std::unordered_map<std::string, std::string>> dest;
|
|
||||||
try {
|
|
||||||
decode_cqcode(cppCode, dest);
|
|
||||||
} catch (illegal_code& code) {
|
|
||||||
return arrayList;
|
|
||||||
}
|
|
||||||
|
|
||||||
jclass HashMap = env->FindClass("java/util/HashMap");
|
|
||||||
jmethodID NewHashMap = env->GetMethodID(HashMap, "<init>", "()V");
|
|
||||||
jclass String = env->FindClass("java/lang/String");
|
|
||||||
jmethodID NewString = env->GetMethodID(String, "<init>", "([BLjava/lang/String;)V");
|
|
||||||
jstring charset = env->NewStringUTF("UTF-8");
|
|
||||||
jmethodID put = env->GetMethodID(HashMap, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
|
|
||||||
for (auto& map : dest) {
|
|
||||||
jobject hashMap = env->NewObject(HashMap, NewHashMap);
|
|
||||||
for (const auto& pair : map) {
|
|
||||||
jbyteArray keyArray = env->NewByteArray((int) pair.first.size());
|
|
||||||
jbyteArray valueArray = env->NewByteArray((int) pair.second.size());
|
|
||||||
env->SetByteArrayRegion(keyArray, 0, (int) pair.first.size(), (jbyte*)pair.first.c_str());
|
|
||||||
env->SetByteArrayRegion(valueArray, 0, (int) pair.second.size(), (jbyte*)pair.second.c_str());
|
|
||||||
auto key = (jstring) env->NewObject(String, NewString, keyArray, charset);
|
|
||||||
auto value = (jstring) env->NewObject(String, NewString, valueArray, charset);
|
|
||||||
env->CallObjectMethod(hashMap, put, key, value);
|
|
||||||
}
|
|
||||||
env->CallBooleanMethod(arrayList, ArrayListAdd, hashMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
env->DeleteLocalRef(ArrayList);
|
|
||||||
env->DeleteLocalRef(HashMap);
|
|
||||||
env->DeleteLocalRef(String);
|
|
||||||
env->DeleteLocalRef(charset);
|
|
||||||
env->ReleaseStringUTFChars(code, cCode);
|
|
||||||
|
|
||||||
return arrayList;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
JNIEXPORT jstring JNICALL
|
|
||||||
Java_moe_fuqiuluo_shamrock_helper_MessageHelper_nativeEncodeCQCode(JNIEnv *env, jobject thiz,
|
|
||||||
jobject segment_list) {
|
|
||||||
jclass List = env->FindClass("java/util/List");
|
|
||||||
jmethodID ListSize = env->GetMethodID(List, "size", "()I");
|
|
||||||
jmethodID ListGet = env->GetMethodID(List, "get", "(I)Ljava/lang/Object;");
|
|
||||||
jclass Map = env->FindClass("java/util/Map");
|
|
||||||
jmethodID MapGet = env->GetMethodID(Map, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
|
||||||
jmethodID entrySetMethod = env->GetMethodID(Map, "entrySet", "()Ljava/util/Set;");
|
|
||||||
jclass setClass = env->FindClass("java/util/Set");
|
|
||||||
jmethodID iteratorMethod = env->GetMethodID(setClass, "iterator", "()Ljava/util/Iterator;");
|
|
||||||
jclass entryClass = env->FindClass("java/util/Map$Entry");
|
|
||||||
jmethodID getKeyMethod = env->GetMethodID(entryClass, "getKey", "()Ljava/lang/Object;");
|
|
||||||
jmethodID getValueMethod = env->GetMethodID(entryClass, "getValue", "()Ljava/lang/Object;");
|
|
||||||
|
|
||||||
std::string result;
|
|
||||||
jint size = env->CallIntMethod(segment_list, ListSize);
|
|
||||||
for (int i = 0; i < size; i++ ) {
|
|
||||||
jobject segment = env->CallObjectMethod(segment_list, ListGet, i);
|
|
||||||
jobject entrySet = env->CallObjectMethod(segment, entrySetMethod);
|
|
||||||
jobject iterator = env->CallObjectMethod(entrySet, iteratorMethod);
|
|
||||||
auto type = (jstring) env->CallObjectMethod(segment, MapGet, env->NewStringUTF("_type"));
|
|
||||||
auto typeString = env->GetStringUTFChars(type, nullptr);
|
|
||||||
if (strcmp(typeString, "text") == 0) {
|
|
||||||
auto text = (jstring) env->CallObjectMethod(segment, MapGet, env->NewStringUTF("text"));
|
|
||||||
auto textString = env->GetStringUTFChars(text, nullptr);
|
|
||||||
std::string tmpValue = textString;
|
|
||||||
replace_string(tmpValue, "&", "&");
|
|
||||||
replace_string(tmpValue, "[", "[");
|
|
||||||
replace_string(tmpValue, "]", "]");
|
|
||||||
replace_string(tmpValue, ",", ",");
|
|
||||||
result.append(tmpValue);
|
|
||||||
env->ReleaseStringUTFChars(text, textString);
|
|
||||||
} else {
|
|
||||||
result.append("[CQ:");
|
|
||||||
result.append(typeString);
|
|
||||||
while (env->CallBooleanMethod(iterator, env->GetMethodID(env->GetObjectClass(iterator), "hasNext", "()Z"))) {
|
|
||||||
jobject entry = env->CallObjectMethod(iterator, env->GetMethodID(env->GetObjectClass(iterator), "next", "()Ljava/lang/Object;"));
|
|
||||||
auto key = (jstring) env->CallObjectMethod(entry, getKeyMethod);
|
|
||||||
auto value = (jstring) env->CallObjectMethod(entry, getValueMethod);
|
|
||||||
auto keyString = env->GetStringUTFChars(key, nullptr);
|
|
||||||
auto valueString = env->GetStringUTFChars(value, nullptr);
|
|
||||||
if (strcmp(keyString, "_type") != 0) {
|
|
||||||
std::string tmpValue = valueString;
|
|
||||||
replace_string(tmpValue, "&", "&");
|
|
||||||
replace_string(tmpValue, "[", "[");
|
|
||||||
replace_string(tmpValue, "]", "]");
|
|
||||||
replace_string(tmpValue, ",", ",");
|
|
||||||
result.append(",").append(keyString).append("=").append(tmpValue);
|
|
||||||
}
|
|
||||||
env->ReleaseStringUTFChars(key, keyString);
|
|
||||||
env->ReleaseStringUTFChars(value, valueString);
|
|
||||||
env->DeleteLocalRef(entry);
|
|
||||||
env->DeleteLocalRef(key);
|
|
||||||
env->DeleteLocalRef(value);
|
|
||||||
}
|
|
||||||
result.append("]");
|
|
||||||
}
|
|
||||||
env->ReleaseStringUTFChars(type, typeString);
|
|
||||||
}
|
|
||||||
|
|
||||||
env->DeleteLocalRef(List);
|
|
||||||
env->DeleteLocalRef(Map);
|
|
||||||
env->DeleteLocalRef(setClass);
|
|
||||||
env->DeleteLocalRef(entryClass);
|
|
||||||
return env->NewStringUTF(result.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jlong JNICALL
|
JNIEXPORT jlong JNICALL
|
||||||
Java_moe_fuqiuluo_shamrock_helper_MessageHelper_insertChatTypeToMsgId(JNIEnv *env, jobject thiz,
|
Java_moe_fuqiuluo_shamrock_helper_MessageHelper_insertChatTypeToMsgId(JNIEnv *env, jobject thiz,
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jstring JNICALL
|
JNIEXPORT jstring JNICALL
|
||||||
Java_moe_fuqiuluo_shamrock_xposed_actions_PullConfig_testNativeLibrary(JNIEnv *env, jobject thiz) {
|
Java_moe_fuqiuluo_shamrock_xposed_actions_interacts_Init_testNativeLibrary(JNIEnv *env, jobject thiz) {
|
||||||
return env->NewStringUTF("加载Shamrock库成功~");
|
return env->NewStringUTF("加载Shamrock库成功~");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,6 +37,26 @@ Java_moe_fuqiuluo_shamrock_utils_MD5_genFileMd5Hex(JNIEnv *env, jobject thiz, js
|
|||||||
return env->NewStringUTF(md5Hex.c_str());
|
return env->NewStringUTF(md5Hex.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jbyteArray JNICALL
|
||||||
|
Java_moe_fuqiuluo_shamrock_utils_MD5_genFileMd5(JNIEnv *env, jobject thiz, jstring file_path) {
|
||||||
|
auto cPathStr = env->GetStringUTFChars(file_path, nullptr);
|
||||||
|
std::filesystem::path filePath(cPathStr);
|
||||||
|
if (!std::filesystem::exists(filePath)) {
|
||||||
|
jclass exClass = env->FindClass("java/io/FileNotFoundException");
|
||||||
|
env->ThrowNew(exClass, "目标文件不存在");
|
||||||
|
env->DeleteLocalRef(exClass);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto file = std::ifstream(filePath.c_str(), std::ios::binary);
|
||||||
|
MD5 md5;
|
||||||
|
md5.update(file);
|
||||||
|
auto md5Bytes = md5.digest();
|
||||||
|
auto jByteArray = env->NewByteArray(16);
|
||||||
|
env->SetByteArrayRegion(jByteArray, 0, 16, reinterpret_cast<const jbyte*>(md5Bytes));
|
||||||
|
return jByteArray;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jstring JNICALL
|
JNIEXPORT jstring JNICALL
|
||||||
Java_moe_fuqiuluo_shamrock_utils_MD5_getMd5Hex(JNIEnv *env, jobject thiz, jbyteArray bytes) {
|
Java_moe_fuqiuluo_shamrock_utils_MD5_getMd5Hex(JNIEnv *env, jobject thiz, jbyteArray bytes) {
|
||||||
|
@ -4,6 +4,7 @@ package moe.fuqiuluo.shamrock
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
@ -52,6 +53,7 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
@ -63,7 +65,9 @@ import androidx.compose.ui.unit.sp
|
|||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import moe.fuqiuluo.shamrock.tools.GlobalUi
|
||||||
import moe.fuqiuluo.shamrock.ui.app.AppRuntime
|
import moe.fuqiuluo.shamrock.ui.app.AppRuntime
|
||||||
import moe.fuqiuluo.shamrock.ui.app.Logger
|
import moe.fuqiuluo.shamrock.ui.app.Logger
|
||||||
import moe.fuqiuluo.shamrock.ui.app.RuntimeState
|
import moe.fuqiuluo.shamrock.ui.app.RuntimeState
|
||||||
@ -85,6 +89,15 @@ class MainActivity : ComponentActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContent {
|
setContent {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
while (true) {
|
||||||
|
delay(5_000) // Delay in milliseconds
|
||||||
|
broadcastToModule {
|
||||||
|
putExtra("__cmd", "switch_status")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalIndication provides NoIndication
|
LocalIndication provides NoIndication
|
||||||
) {
|
) {
|
||||||
@ -94,8 +107,9 @@ class MainActivity : ComponentActivity() {
|
|||||||
isAppearanceLightStatusBars = true
|
isAppearanceLightStatusBars = true
|
||||||
}
|
}
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, true)
|
WindowCompat.setDecorFitsSystemWindows(window, true)
|
||||||
broadcastToModule { putExtra("__cmd", "fetchPort") }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GlobalUi = Handler(mainLooper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,6 +134,7 @@ private fun AppMainView() {
|
|||||||
val coreVersion = remember { mutableStateOf(getShamrockVersion(context)) }
|
val coreVersion = remember { mutableStateOf(getShamrockVersion(context)) }
|
||||||
val coreName = remember { mutableStateOf("Xposed") }
|
val coreName = remember { mutableStateOf("Xposed") }
|
||||||
val voiceSwitch = remember { mutableStateOf(false) }
|
val voiceSwitch = remember { mutableStateOf(false) }
|
||||||
|
@Suppress("LocalVariableName") val LocalString = LocalString.init()
|
||||||
|
|
||||||
if (!AppRuntime.isInit) {
|
if (!AppRuntime.isInit) {
|
||||||
AppRuntime.state = remember {
|
AppRuntime.state = remember {
|
||||||
@ -140,23 +155,22 @@ private fun AppMainView() {
|
|||||||
mutableStateOf("2854200454")
|
mutableStateOf("2854200454")
|
||||||
}
|
}
|
||||||
it.nick = remember {
|
it.nick = remember {
|
||||||
mutableStateOf("测试昵称")
|
mutableStateOf(LocalString.testName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AppRuntime.requestCount = remember { mutableIntStateOf(0) }
|
AppRuntime.requestCount = remember { mutableIntStateOf(0) }
|
||||||
|
|
||||||
AppRuntime.isInit = false
|
AppRuntime.isInit = true
|
||||||
}
|
}
|
||||||
|
|
||||||
val ctx = LocalContext.current
|
val ctx = LocalContext.current
|
||||||
@Suppress("LocalVariableName") val LocalString = LocalString
|
LaunchedEffect(isFined) {
|
||||||
LaunchedEffect(isFined.value) {
|
|
||||||
if (isFined.value) {
|
if (isFined.value) {
|
||||||
AppRuntime.log("日志框架激活成功,开放操作许可。")
|
AppRuntime.log(LocalString.logCentralLoadSuccessfully)
|
||||||
Toast.makeText(ctx, LocalString.frameworkYes, Toast.LENGTH_SHORT).show()
|
Toast.makeText(ctx, LocalString.frameworkYes, Toast.LENGTH_SHORT).show()
|
||||||
} else {
|
} else {
|
||||||
AppRuntime.log("日志框架处于未激活状态,请检查。")
|
AppRuntime.log(LocalString.logCentralLoadFailed)
|
||||||
Toast.makeText(ctx, LocalString.frameworkNo, Toast.LENGTH_SHORT).show()
|
Toast.makeText(ctx, LocalString.frameworkNo, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -282,58 +296,11 @@ private fun AnimatedTab(
|
|||||||
val lastSelectedState = remember {
|
val lastSelectedState = remember {
|
||||||
mutableIntStateOf(0)
|
mutableIntStateOf(0)
|
||||||
}
|
}
|
||||||
val enter = remember {
|
|
||||||
scaleIn(animationSpec = TweenSpec(150, easing = FastOutLinearInEasing))
|
|
||||||
}
|
|
||||||
val exit = remember {
|
|
||||||
scaleOut(animationSpec = TweenSpec(150, easing = FastOutSlowInEasing))
|
|
||||||
}
|
|
||||||
|
|
||||||
val defaultConst = SELECTED_TABLE[index * 2]
|
val defaultConst = SELECTED_TABLE[index * 2]
|
||||||
val selectedConst = SELECTED_TABLE[(index * 2) + 1]
|
val selectedConst = SELECTED_TABLE[(index * 2) + 1]
|
||||||
val isFirst: Boolean = (lastSelectedState.value and defaultConst) != defaultConst
|
val isFirst: Boolean = (lastSelectedState.value and defaultConst) != defaultConst
|
||||||
|
|
||||||
var icon: @Composable (() -> Unit)? = null
|
|
||||||
var text: @Composable (() -> Unit)? = null
|
|
||||||
|
|
||||||
if (curSelected) {
|
|
||||||
text = {
|
|
||||||
AnimatedVisibility(visibleState = MutableTransitionState(false).also {
|
|
||||||
it.targetState =
|
|
||||||
isFirst || lastSelectedState.value and selectedConst == selectedConst
|
|
||||||
}, enter = enter, exit = exit, modifier = Modifier) {
|
|
||||||
Text(
|
|
||||||
text = titleWithIcon.first,
|
|
||||||
color = GlobalColor.TabItem,
|
|
||||||
fontSize = 15.sp,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(bottom = 5.dp)
|
|
||||||
.indication(
|
|
||||||
remember { MutableInteractionSource() },
|
|
||||||
rememberRipple(color = Color.Transparent)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
icon = {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(id = titleWithIcon.second),
|
|
||||||
contentDescription = titleWithIcon.first,
|
|
||||||
tint = Color.Unspecified,
|
|
||||||
modifier = Modifier
|
|
||||||
.height(24.dp)
|
|
||||||
.width(24.dp)
|
|
||||||
.padding(bottom = 5.dp)
|
|
||||||
.indication(
|
|
||||||
remember { MutableInteractionSource() },
|
|
||||||
rememberRipple(color = Color.Transparent)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ShamrockTab(
|
ShamrockTab(
|
||||||
selected = curSelected,
|
selected = curSelected,
|
||||||
onClick = {
|
onClick = {
|
||||||
@ -341,11 +308,13 @@ private fun AnimatedTab(
|
|||||||
state.scrollToPage(index, 0f)
|
state.scrollToPage(index, 0f)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
text = text,
|
|
||||||
icon = icon,
|
|
||||||
selectedContentColor = Color.Transparent,
|
selectedContentColor = Color.Transparent,
|
||||||
unselectedContentColor = Color.Transparent,
|
unselectedContentColor = Color.Transparent,
|
||||||
indication = null
|
indication = null,
|
||||||
|
titleWithIcon = titleWithIcon,
|
||||||
|
visibleState = MutableTransitionState(false).also {
|
||||||
|
it.targetState = isFirst || lastSelectedState.value and selectedConst == selectedConst
|
||||||
|
}
|
||||||
)
|
)
|
||||||
lastSelectedState.value.let {
|
lastSelectedState.value.let {
|
||||||
var tmp = it
|
var tmp = it
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
package moe.fuqiuluo.shamrock.app.config
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
package moe.fuqiuluo.shamrock.app.config
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import moe.fuqiuluo.shamrock.config.ConfigKey
|
||||||
|
import moe.fuqiuluo.shamrock.ui.service.internal.broadcastToModule
|
||||||
|
|
||||||
|
object ShamrockConfig {
|
||||||
|
internal fun getConfigPref(ctx: Context) = ctx.getSharedPreferences("config", 0)
|
||||||
|
|
||||||
|
internal inline operator fun <reified Type> get(ctx: Context, key: ConfigKey<Type>): Type {
|
||||||
|
val preferences = getConfigPref(ctx)
|
||||||
|
return when(Type::class) {
|
||||||
|
Int::class -> preferences.getInt(key.name(), key.default() as Int) as Type
|
||||||
|
Long::class -> preferences.getLong(key.name(), key.default() as Long) as Type
|
||||||
|
String::class -> preferences.getString(key.name(), key.default() as String) as Type
|
||||||
|
Boolean::class -> preferences.getBoolean(key.name(), key.default() as Boolean) as Type
|
||||||
|
else -> throw IllegalArgumentException("Unsupported type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline operator fun <reified Type> set(ctx: Context, key: ConfigKey<Type>, value: Type) {
|
||||||
|
val preferences = getConfigPref(ctx)
|
||||||
|
val editor = preferences.edit()
|
||||||
|
when(Type::class) {
|
||||||
|
Int::class -> editor.putInt(key.name(), value as Int)
|
||||||
|
Long::class -> editor.putLong(key.name(), value as Long)
|
||||||
|
String::class -> editor.putString(key.name(), value as String)
|
||||||
|
Boolean::class -> editor.putBoolean(key.name(), value as Boolean)
|
||||||
|
else -> throw IllegalArgumentException("Unsupported type")
|
||||||
|
}
|
||||||
|
editor.apply()
|
||||||
|
}
|
||||||
|
}
|
@ -1,328 +0,0 @@
|
|||||||
package moe.fuqiuluo.shamrock.ui.app
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import moe.fuqiuluo.shamrock.ui.service.internal.broadcastToModule
|
|
||||||
|
|
||||||
object ShamrockConfig {
|
|
||||||
fun getSSLKeyPath(ctx: Context): String {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getString("key_store", "")!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setSSLKeyPath(ctx: Context, path: String) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putString("key_store", path).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSSLPort(ctx: Context): Int {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getInt("ssl_port", 5701)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setSSLPort(ctx: Context, port: Int) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putInt("ssl_port", port).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSSLAlias(ctx: Context): String {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getString("ssl_alias", "")!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setSSLAlias(ctx: Context, alias: String) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putString("ssl_alias", alias).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSSLPwd(ctx: Context): String {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getString("ssl_pwd", "")!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setSSLPwd(ctx: Context, alias: String) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putString("ssl_pwd", alias).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSSLPrivatePwd(ctx: Context): String {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getString("ssl_private_pwd", "")!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setSSLPrivatePwd(ctx: Context, alias: String) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putString("ssl_private_pwd", alias).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getHttpAddr(ctx: Context): String {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getString("http_addr", "")!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setHttpAddr(ctx: Context, v: String) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putString("http_addr", v).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isPro(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("pro_api", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setPro(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("pro_api", v).apply()
|
|
||||||
ctx.broadcastToModule {
|
|
||||||
putExtra("type", "restart")
|
|
||||||
putExtra("__cmd", "change_port")
|
|
||||||
}
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getToken(ctx: Context): String {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getString("token", null) ?: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setToken(ctx: Context, v: String?) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putString("token", v).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isWs(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("ws", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setWs(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("ws", v).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isWsClient(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("ws_client", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setWsClient(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("ws_client", v).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isTablet(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("tablet", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setTablet(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("tablet", v).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isUseCQCode(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("use_cqcode", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setUseCQCode(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("use_cqcode", v).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isWebhook(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("webhook", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setWebhook(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("webhook", v).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWsAddr(ctx: Context): String {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getString("ws_addr", "")!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setWsAddr(ctx: Context, v: String) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putString("ws_addr", v).apply()
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getHttpPort(ctx: Context): Int {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getInt("port", 5700)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setHttpPort(ctx: Context, v: Int) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putInt("port", v).apply()
|
|
||||||
ctx.broadcastToModule {
|
|
||||||
putExtra("type", "port")
|
|
||||||
putExtra("port", v)
|
|
||||||
putExtra("__cmd", "change_port")
|
|
||||||
}
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWsPort(ctx: Context): Int {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getInt("ws_port", 5800)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setWsPort(ctx: Context, v: Int) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putInt("ws_port", v).apply()
|
|
||||||
ctx.broadcastToModule {
|
|
||||||
putExtra("type", "ws_port")
|
|
||||||
putExtra("port", v)
|
|
||||||
putExtra("__cmd", "change_port")
|
|
||||||
}
|
|
||||||
pushUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun is2B(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("2B", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun set2B(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("2B", v).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setAutoClean(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("auto_clear", v).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isAutoClean(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("auto_clear", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isDebug(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("debug", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setDebug(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("debug", v).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isInjectPacket(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("inject_packet", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setInjectPacket(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("inject_packet", v).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun enableAutoStart(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("enable_auto_start", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun allowShell(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("shell", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setAutoStart(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("enable_auto_start", v).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setShellStatus(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("shell", v).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun enableSelfMsg(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("enable_self_msg", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setEnableSelfMsg(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("enable_self_msg", v).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isEchoNumber(ctx: Context): Boolean {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return preferences.getBoolean("echo_number", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setEchoNumber(ctx: Context, v: Boolean) {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
preferences.edit().putBoolean("echo_number", v).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getConfigMap(ctx: Context): Map<String, Any?> {
|
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
|
||||||
return mapOf(
|
|
||||||
"tablet" to preferences.getBoolean("tablet", false),
|
|
||||||
"port" to preferences.getInt("port", 5700),
|
|
||||||
"ws" to preferences.getBoolean("ws", false),
|
|
||||||
"ws_port" to preferences.getInt("ws_port", 5800),
|
|
||||||
"ssl_port" to preferences.getInt("ssl_port", 5701),
|
|
||||||
"http" to preferences.getBoolean("webhook", false),
|
|
||||||
"http_addr" to preferences.getString("http_addr", ""),
|
|
||||||
"ws_client" to preferences.getBoolean("ws_client", false),
|
|
||||||
"use_cqcode" to preferences.getBoolean("use_cqcode", false),
|
|
||||||
"ws_addr" to preferences.getString("ws_addr", ""),
|
|
||||||
"ssl_alias" to preferences.getString("ssl_alias", ""),
|
|
||||||
"pro_api" to preferences.getBoolean("pro_api", false),
|
|
||||||
"token" to preferences.getString("token", null),
|
|
||||||
"ssl_pwd" to preferences.getString("ssl_pwd", ""),
|
|
||||||
"inject_packet" to preferences.getBoolean("inject_packet", false),
|
|
||||||
"debug" to preferences.getBoolean("debug", false),
|
|
||||||
"auto_clear" to preferences.getBoolean("auto_clear", false),
|
|
||||||
"ssl_private_pwd" to preferences.getString("ssl_private_pwd", ""),
|
|
||||||
"key_store" to preferences.getString("key_store", ""),
|
|
||||||
"enable_self_msg" to preferences.getBoolean("enable_self_msg", false),
|
|
||||||
"echo_number" to preferences.getBoolean("echo_number", false),
|
|
||||||
"shell" to preferences.getBoolean("shell", false),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun pushUpdate(ctx: Context) {
|
|
||||||
ctx.broadcastToModule {
|
|
||||||
getConfigMap(ctx).forEach { (key, value) ->
|
|
||||||
if (value == null) {
|
|
||||||
val v: String? = null
|
|
||||||
this.putExtra(key, v)
|
|
||||||
} else {
|
|
||||||
when (value) {
|
|
||||||
is Int -> this.putExtra(key, value)
|
|
||||||
is Long -> this.putExtra(key, value)
|
|
||||||
is Short -> this.putExtra(key, value)
|
|
||||||
is Byte -> this.putExtra(key, value)
|
|
||||||
is String -> this.putExtra(key, value)
|
|
||||||
is ByteArray -> this.putExtra(key, value)
|
|
||||||
is Boolean -> this.putExtra(key, value)
|
|
||||||
is Float -> this.putExtra(key, value)
|
|
||||||
is Double -> this.putExtra(key, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
putExtra("__cmd", "push_config")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,6 @@ import android.content.ClipData
|
|||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
@ -25,6 +24,7 @@ import androidx.compose.material3.Divider
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
@ -45,11 +45,14 @@ import coil.compose.rememberAsyncImagePainter
|
|||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import coil.size.Size
|
import coil.size.Size
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import moe.fuqiuluo.shamrock.R
|
import moe.fuqiuluo.shamrock.R
|
||||||
import moe.fuqiuluo.shamrock.ui.app.AppRuntime
|
import moe.fuqiuluo.shamrock.ui.app.AppRuntime
|
||||||
import moe.fuqiuluo.shamrock.ui.app.Level
|
import moe.fuqiuluo.shamrock.ui.app.Level
|
||||||
import moe.fuqiuluo.shamrock.ui.app.ShamrockConfig
|
import moe.fuqiuluo.shamrock.app.config.ShamrockConfig
|
||||||
|
import moe.fuqiuluo.shamrock.config.*
|
||||||
import moe.fuqiuluo.shamrock.ui.theme.GlobalColor
|
import moe.fuqiuluo.shamrock.ui.theme.GlobalColor
|
||||||
|
import moe.fuqiuluo.shamrock.ui.theme.LocalString
|
||||||
import moe.fuqiuluo.shamrock.ui.theme.ThemeColor
|
import moe.fuqiuluo.shamrock.ui.theme.ThemeColor
|
||||||
import moe.fuqiuluo.shamrock.ui.tools.InputDialog
|
import moe.fuqiuluo.shamrock.ui.tools.InputDialog
|
||||||
|
|
||||||
@ -70,111 +73,7 @@ fun DashboardFragment(
|
|||||||
AccountCard(nick, uin)
|
AccountCard(nick, uin)
|
||||||
InformationCard(ctx)
|
InformationCard(ctx)
|
||||||
APIInfoCard(ctx)
|
APIInfoCard(ctx)
|
||||||
FunctionCard(scope, ctx, "功能设置")
|
FunctionCard(scope, ctx, LocalString.functionSetting)
|
||||||
SSLCard(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun SSLCard(ctx: Context) {
|
|
||||||
ActionBox(
|
|
||||||
modifier = Modifier.padding(top = 12.dp),
|
|
||||||
painter = painterResource(id = R.drawable.baseline_security_24),
|
|
||||||
title = "SSL配置"
|
|
||||||
) {
|
|
||||||
Column {
|
|
||||||
Divider(
|
|
||||||
modifier = Modifier,
|
|
||||||
color = GlobalColor.Divider,
|
|
||||||
thickness = 0.2.dp
|
|
||||||
)
|
|
||||||
|
|
||||||
val sslPort = remember { mutableStateOf(ShamrockConfig.getSSLPort(ctx).toString()) }
|
|
||||||
TextItem(
|
|
||||||
title = "SSL端口",
|
|
||||||
desc = "端口范围在0~65565,并确保可用。",
|
|
||||||
text = sslPort,
|
|
||||||
hint = "请输入端口号",
|
|
||||||
error = "端口范围应在0~65565",
|
|
||||||
checker = {
|
|
||||||
it.isNotBlank() && kotlin.runCatching { it.toInt() in 0..65565 }.getOrDefault(false)
|
|
||||||
},
|
|
||||||
confirm = {
|
|
||||||
val newPort = sslPort.value.toInt()
|
|
||||||
ShamrockConfig.setSSLPort(ctx, newPort)
|
|
||||||
AppRuntime.log("设置SSL(HTTP)端口为$newPort,立即生效尝试中。")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
val keyStore = remember { mutableStateOf(ShamrockConfig.getSSLKeyPath(ctx)) }
|
|
||||||
TextItem(
|
|
||||||
title = "SSL证书",
|
|
||||||
desc = "BKS签名的证书。",
|
|
||||||
text = keyStore,
|
|
||||||
hint = "输入证书路径",
|
|
||||||
error = "证书路径不合法或不存在",
|
|
||||||
checker = {
|
|
||||||
it.isNotBlank()
|
|
||||||
},
|
|
||||||
confirm = {
|
|
||||||
val new = keyStore.value
|
|
||||||
ShamrockConfig.setSSLKeyPath(ctx, new)
|
|
||||||
AppRuntime.log("设置SSL证书为[$new]。")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
val alias = remember { mutableStateOf(ShamrockConfig.getSSLAlias(ctx)) }
|
|
||||||
TextItem(
|
|
||||||
title = "SSL别名",
|
|
||||||
desc = "BKS签名的别名,确保大小写区分正确。",
|
|
||||||
text = alias,
|
|
||||||
hint = "输入签名别名",
|
|
||||||
error = "别名不合法",
|
|
||||||
checker = {
|
|
||||||
it.isNotBlank()
|
|
||||||
},
|
|
||||||
confirm = {
|
|
||||||
val new = alias.value
|
|
||||||
ShamrockConfig.setSSLAlias(ctx, new)
|
|
||||||
AppRuntime.log("设置SSL别名为[$new]。")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
val sslPwd = remember { mutableStateOf(ShamrockConfig.getSSLPwd(ctx)) }
|
|
||||||
TextItem(
|
|
||||||
title = "SSL密码",
|
|
||||||
desc = "BKS签名的密码。",
|
|
||||||
text = sslPwd,
|
|
||||||
hint = "输入签名密码",
|
|
||||||
error = "密码不合法",
|
|
||||||
checker = {
|
|
||||||
it.isNotBlank()
|
|
||||||
},
|
|
||||||
confirm = {
|
|
||||||
val new = sslPwd.value
|
|
||||||
ShamrockConfig.setSSLPwd(ctx, new)
|
|
||||||
AppRuntime.log("设置SSL密码为[$new]。")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
val sslPrivatePwd = remember { mutableStateOf(ShamrockConfig.getSSLPrivatePwd(ctx)) }
|
|
||||||
TextItem(
|
|
||||||
title = "SSL Private密码",
|
|
||||||
desc = "BKS签名的Private密码。",
|
|
||||||
text = sslPrivatePwd,
|
|
||||||
hint = "输入Private密码",
|
|
||||||
error = "密码不合法",
|
|
||||||
checker = {
|
|
||||||
it.isNotBlank()
|
|
||||||
},
|
|
||||||
confirm = {
|
|
||||||
val new = sslPrivatePwd.value
|
|
||||||
ShamrockConfig.setSSLPrivatePwd(ctx, new)
|
|
||||||
AppRuntime.log("设置SSL Private密码为[$new]。")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,95 +93,35 @@ private fun APIInfoCard(
|
|||||||
thickness = 0.2.dp
|
thickness = 0.2.dp
|
||||||
)
|
)
|
||||||
|
|
||||||
val wsPort = remember { mutableStateOf(ShamrockConfig.getWsPort(ctx).toString()) }
|
val rpcPort = remember { mutableStateOf(ShamrockConfig[ctx, RPCPort].toString()) }
|
||||||
val port = remember { mutableStateOf(ShamrockConfig.getHttpPort(ctx).toString()) }
|
|
||||||
TextItem(
|
TextItem(
|
||||||
title = "主动HTTP端口",
|
title = "RPC服务端口",
|
||||||
desc = "端口范围在0~65565,并确保可用。",
|
desc = "端口范围在0~65565,并确保可用。",
|
||||||
text = port,
|
text = rpcPort,
|
||||||
hint = "请输入端口号",
|
hint = "请输入端口号",
|
||||||
error = "端口范围应在0~65565",
|
error = "端口范围应在0~65565",
|
||||||
checker = {
|
checker = {
|
||||||
it.isNotBlank() && kotlin.runCatching { it.toInt() in 0..65565 }.getOrDefault(false) && wsPort.value != it
|
it.isNotBlank() && kotlin.runCatching { it.toInt() in 0..65565 }
|
||||||
|
.getOrDefault(false) && rpcPort.value != it
|
||||||
},
|
},
|
||||||
confirm = {
|
confirm = {
|
||||||
val newPort = port.value.toInt()
|
val newPort = rpcPort.value.toInt()
|
||||||
ShamrockConfig.setHttpPort(ctx, newPort)
|
ShamrockConfig[ctx, RPCPort] = newPort
|
||||||
AppRuntime.log("设置主动HTTP监听端口为$newPort,立即生效尝试中。")
|
AppRuntime.log("设置主动HTTP监听端口为$newPort,立即生效尝试中。")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val rpcAddress = remember { mutableStateOf(ShamrockConfig[ctx, RPCAddress]) }
|
||||||
TextItem(
|
TextItem(
|
||||||
title = "主动WebSocket端口",
|
title = "回调RPC地址",
|
||||||
desc = "端口范围在0~65565,并确保可用。",
|
desc = "例如:kritor.support:8081",
|
||||||
text = wsPort,
|
text = rpcAddress,
|
||||||
hint = "请输入端口号",
|
|
||||||
error = "端口范围应在0~65565",
|
|
||||||
checker = {
|
|
||||||
it.isNotBlank() && kotlin.runCatching { it.toInt() in 0..65565 }.getOrDefault(false) && it != port.value
|
|
||||||
},
|
|
||||||
confirm = {
|
|
||||||
val newPort = wsPort.value.toInt()
|
|
||||||
ShamrockConfig.setWsPort(ctx, newPort)
|
|
||||||
AppRuntime.log("设置主动WebSocket监听端口为$newPort。")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
val webHookAddress = remember { mutableStateOf(ShamrockConfig.getHttpAddr(ctx)) }
|
|
||||||
TextItem(
|
|
||||||
title = "回调HTTP地址",
|
|
||||||
desc = "例如:http://shamrock.moe:80。",
|
|
||||||
text = webHookAddress,
|
|
||||||
hint = "请输入回调地址",
|
hint = "请输入回调地址",
|
||||||
error = "输入的地址不合法",
|
error = "输入的地址不合法",
|
||||||
checker = {
|
checker = { true },
|
||||||
it.isNotBlank()
|
|
||||||
},
|
|
||||||
confirm = {
|
confirm = {
|
||||||
if (it.startsWith("http://") || it.startsWith("https://")) {
|
ShamrockConfig[ctx, RPCAddress] = rpcAddress.value
|
||||||
ShamrockConfig.setHttpAddr(ctx, webHookAddress.value)
|
AppRuntime.log("设置回调RPC地址为[${rpcAddress.value}]。")
|
||||||
AppRuntime.log("设置回调HTTP地址为[${webHookAddress.value}]。")
|
|
||||||
} else {
|
|
||||||
Toast.makeText(ctx, "回调地址不合法", Toast.LENGTH_SHORT).show()
|
|
||||||
webHookAddress.value = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
val wsAddress = remember { mutableStateOf(ShamrockConfig.getWsAddr(ctx)) }
|
|
||||||
TextItem(
|
|
||||||
title = "被动WebSocket地址",
|
|
||||||
desc = "例如:ws://shamrock.moe:81,多个使用逗号分隔。",
|
|
||||||
text = wsAddress,
|
|
||||||
hint = "请输入被动地址",
|
|
||||||
error = "输入的地址不合法",
|
|
||||||
checker = {
|
|
||||||
true
|
|
||||||
},
|
|
||||||
confirm = {
|
|
||||||
if (it.startsWith("ws://") || it.startsWith("wss://") || it.isBlank()) {
|
|
||||||
ShamrockConfig.setWsAddr(ctx, wsAddress.value)
|
|
||||||
AppRuntime.log("设置被动WebSocket地址为[${wsAddress.value}]。")
|
|
||||||
} else {
|
|
||||||
Toast.makeText(ctx, "被动WebSocket地址不合法", Toast.LENGTH_SHORT).show()
|
|
||||||
wsAddress.value = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
val authToken = remember { mutableStateOf(ShamrockConfig.getToken(ctx)) }
|
|
||||||
TextItem(
|
|
||||||
title = "鉴权Token",
|
|
||||||
desc = "用于鉴权的Token。",
|
|
||||||
text = authToken,
|
|
||||||
hint = "请填写鉴权token",
|
|
||||||
error = "输入的参数不合法",
|
|
||||||
checker = {
|
|
||||||
it.length in 0 .. 36
|
|
||||||
},
|
|
||||||
confirm = {
|
|
||||||
ShamrockConfig.setToken(ctx, authToken.value)
|
|
||||||
AppRuntime.log("设置鉴权Token为[${authToken.value}]。")
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -315,59 +154,59 @@ private fun FunctionCard(
|
|||||||
Function(
|
Function(
|
||||||
title = "强制平板模式",
|
title = "强制平板模式",
|
||||||
desc = "强制QQ使用平板模式,实现共存登录。",
|
desc = "强制QQ使用平板模式,实现共存登录。",
|
||||||
isSwitch = ShamrockConfig.isTablet(ctx)
|
isSwitch = ShamrockConfig[ctx, ForceTablet]
|
||||||
) {
|
) {
|
||||||
ShamrockConfig.setTablet(ctx, it)
|
ShamrockConfig[ctx, ForceTablet] = it
|
||||||
return@Function true
|
return@Function true
|
||||||
}
|
}
|
||||||
|
|
||||||
Function(
|
Function(
|
||||||
title = "HTTP回调",
|
title = "主动RPC",
|
||||||
desc = "OneBot标准的HTTPAPI回调,Shamrock作为Client。",
|
desc = "Kritor协议实现RPC",
|
||||||
isSwitch = ShamrockConfig.isWebhook(ctx)
|
isSwitch = ShamrockConfig[ctx, ActiveRPC]
|
||||||
) {
|
) {
|
||||||
ShamrockConfig.setWebhook(ctx, it)
|
ShamrockConfig[ctx, ActiveRPC] = it
|
||||||
return@Function true
|
return@Function true
|
||||||
}
|
}
|
||||||
|
|
||||||
Function(
|
Function(
|
||||||
title = "消息格式为CQ码",
|
title = "被动RPC",
|
||||||
desc = "HTTPAPI回调的消息格式,关闭则为消息段。",
|
desc = "Kritor协议实现RPC",
|
||||||
isSwitch = ShamrockConfig.isUseCQCode(ctx)
|
isSwitch = ShamrockConfig[ctx, PassiveRPC]
|
||||||
) {
|
) {
|
||||||
ShamrockConfig.setUseCQCode(ctx, it)
|
ShamrockConfig[ctx, PassiveRPC] = it
|
||||||
return@Function true
|
return@Function true
|
||||||
}
|
}
|
||||||
|
|
||||||
Function(
|
run {
|
||||||
title = "主动WebSocket",
|
val uploadResourceGroup = remember { mutableStateOf(ShamrockConfig[ctx, ResourceGroup]) }
|
||||||
desc = "OneBot标准WebSocket,Shamrock作为Server。",
|
Column(
|
||||||
isSwitch = ShamrockConfig.isWs(ctx)
|
modifier = Modifier
|
||||||
) {
|
.absolutePadding(left = 8.dp, right = 8.dp, top = 12.dp, bottom = 0.dp)
|
||||||
ShamrockConfig.setWs(ctx, it)
|
) {
|
||||||
return@Function true
|
Text(
|
||||||
|
modifier = Modifier.padding(2.dp),
|
||||||
|
text = "用来上传资源的群聊,错误的资源上传终点可能导致封禁,请自建一个群聊并填写在下方。",
|
||||||
|
color = Color.Red,
|
||||||
|
fontSize = 11.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
TextItem(
|
||||||
|
title = "接受资源群聊",
|
||||||
|
desc = "用来上传资源的群聊,请自建一个群聊并填写在下方。",
|
||||||
|
text = uploadResourceGroup,
|
||||||
|
hint = "请输入群号",
|
||||||
|
error = "群号不合法",
|
||||||
|
checker = {
|
||||||
|
it.isNotBlank() && it.toULongOrNull() != null
|
||||||
|
},
|
||||||
|
confirm = {
|
||||||
|
val groupId = uploadResourceGroup.value
|
||||||
|
ShamrockConfig[ctx, ResourceGroup] = groupId
|
||||||
|
AppRuntime.log("设置接受资源群聊为[$groupId]。")
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Function(
|
|
||||||
title = "被动WebSocket",
|
|
||||||
desc = "OneBot标准WebSocket,Shamrock作为Client。",
|
|
||||||
isSwitch = ShamrockConfig.isWsClient(ctx)
|
|
||||||
) {
|
|
||||||
ShamrockConfig.setWsClient(ctx, it)
|
|
||||||
return@Function true
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Function(
|
|
||||||
title = "专业级接口",
|
|
||||||
desc = "如果你不知道你在做什么,请不要开启本功能。",
|
|
||||||
descColor = Color.Red,
|
|
||||||
isSwitch = ShamrockConfig.isPro(ctx)
|
|
||||||
) {
|
|
||||||
ShamrockConfig.setPro(ctx, it)
|
|
||||||
AppRuntime.log("专业级API = $it", Level.WARN)
|
|
||||||
return@Function true
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -446,9 +285,7 @@ private fun InfoItem(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.combinedClickable(onDoubleClick = {
|
.combinedClickable(onDoubleClick = {
|
||||||
doubleClick?.invoke(content)
|
doubleClick?.invoke(content)
|
||||||
}) {
|
}) { true }
|
||||||
true
|
|
||||||
}
|
|
||||||
,
|
,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package moe.fuqiuluo.shamrock.ui.fragment
|
package moe.fuqiuluo.shamrock.ui.fragment
|
||||||
|
|
||||||
import android.widget.Toast
|
import android.content.Context
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.absolutePadding
|
import androidx.compose.foundation.layout.absolutePadding
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
@ -22,7 +22,15 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import moe.fuqiuluo.shamrock.R
|
import moe.fuqiuluo.shamrock.R
|
||||||
import moe.fuqiuluo.shamrock.ui.app.AppRuntime
|
import moe.fuqiuluo.shamrock.ui.app.AppRuntime
|
||||||
import moe.fuqiuluo.shamrock.ui.app.ShamrockConfig
|
import moe.fuqiuluo.shamrock.ui.app.Level
|
||||||
|
import moe.fuqiuluo.shamrock.app.config.ShamrockConfig
|
||||||
|
import moe.fuqiuluo.shamrock.config.AliveReply
|
||||||
|
import moe.fuqiuluo.shamrock.config.AntiJvmTrace
|
||||||
|
import moe.fuqiuluo.shamrock.config.B2Mode
|
||||||
|
import moe.fuqiuluo.shamrock.config.DebugMode
|
||||||
|
import moe.fuqiuluo.shamrock.config.EnableOldBDH
|
||||||
|
import moe.fuqiuluo.shamrock.config.EnableSelfMessage
|
||||||
|
import moe.fuqiuluo.shamrock.ui.service.handlers.InitHandler
|
||||||
import moe.fuqiuluo.shamrock.ui.theme.GlobalColor
|
import moe.fuqiuluo.shamrock.ui.theme.GlobalColor
|
||||||
import moe.fuqiuluo.shamrock.ui.theme.LocalString
|
import moe.fuqiuluo.shamrock.ui.theme.LocalString
|
||||||
import moe.fuqiuluo.shamrock.ui.tools.NoticeTextDialog
|
import moe.fuqiuluo.shamrock.ui.tools.NoticeTextDialog
|
||||||
@ -46,10 +54,11 @@ fun LabFragment() {
|
|||||||
}
|
}
|
||||||
NoticeTextDialog(
|
NoticeTextDialog(
|
||||||
openDialog = showNoticeDialog,
|
openDialog = showNoticeDialog,
|
||||||
title = "温馨提示",
|
title = LocalString.warnTitle,
|
||||||
text = "实验室功能会导致一些奇怪的问题,请谨慎使用!"
|
text = LocalString.labWarning
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val LocalString = LocalString
|
||||||
ActionBox(
|
ActionBox(
|
||||||
modifier = Modifier.padding(top = 12.dp),
|
modifier = Modifier.padding(top = 12.dp),
|
||||||
painter = painterResource(id = R.drawable.baseline_preview_24),
|
painter = painterResource(id = R.drawable.baseline_preview_24),
|
||||||
@ -63,24 +72,24 @@ fun LabFragment() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
Function(
|
Function(
|
||||||
title = "中二病模式",
|
title = LocalString.b2Mode,
|
||||||
desc = "也许会导致奇怪的问题,大抵就是你看不懂罢了。",
|
desc = LocalString.b2ModeDesc,
|
||||||
descColor = it,
|
descColor = it,
|
||||||
isSwitch = ShamrockConfig.is2B(ctx)
|
isSwitch = ShamrockConfig[ctx, B2Mode]
|
||||||
) {
|
) {
|
||||||
ShamrockConfig.set2B(ctx, it)
|
ShamrockConfig[ctx, B2Mode] = it
|
||||||
scope.toast(ctx, "重启生效哦!")
|
scope.toast(ctx, LocalString.restartToast)
|
||||||
return@Function true
|
return@Function true
|
||||||
}
|
}
|
||||||
|
|
||||||
Function(
|
Function(
|
||||||
title = "显示调试日志",
|
title = LocalString.showDebugLog,
|
||||||
desc = "会导致日志刷屏。",
|
desc = LocalString.showDebugLogDesc,
|
||||||
descColor = it,
|
descColor = it,
|
||||||
isSwitch = ShamrockConfig.isDebug(ctx)
|
isSwitch = ShamrockConfig[ctx, DebugMode]
|
||||||
) {
|
) {
|
||||||
ShamrockConfig.setDebug(ctx, it)
|
ShamrockConfig[ctx, DebugMode] = it
|
||||||
ShamrockConfig.pushUpdate(ctx)
|
InitHandler.update(ctx)
|
||||||
return@Function true
|
return@Function true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,8 +98,8 @@ fun LabFragment() {
|
|||||||
ActionBox(
|
ActionBox(
|
||||||
modifier = Modifier.padding(top = 12.dp),
|
modifier = Modifier.padding(top = 12.dp),
|
||||||
painter = painterResource(id = R.drawable.round_logo_dev_24),
|
painter = painterResource(id = R.drawable.round_logo_dev_24),
|
||||||
title = "实验功能"
|
title = "基础设置"
|
||||||
) {
|
) { color ->
|
||||||
Column {
|
Column {
|
||||||
Divider(
|
Divider(
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
@ -99,50 +108,86 @@ fun LabFragment() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
Function(
|
Function(
|
||||||
title = "自动清理QQ垃圾",
|
title = "自回复测试",
|
||||||
desc = "也许会导致奇怪的问题(无效)。",
|
desc = "发送[ping],机器人发送一个具有调试信息的返回。",
|
||||||
descColor = it,
|
descColor = color,
|
||||||
isSwitch = ShamrockConfig.isAutoClean(ctx)
|
isSwitch = ShamrockConfig[ctx, AliveReply]
|
||||||
) {
|
) {
|
||||||
ShamrockConfig.setAutoClean(ctx, it)
|
ShamrockConfig[ctx, AliveReply] = it
|
||||||
ShamrockConfig.pushUpdate(ctx)
|
|
||||||
return@Function false
|
|
||||||
}
|
|
||||||
|
|
||||||
Function(
|
|
||||||
title = "拦截QQ无用收包",
|
|
||||||
desc = "测试阶段,可能导致网络异常或掉线。",
|
|
||||||
descColor = it,
|
|
||||||
isSwitch = ShamrockConfig.isInjectPacket(ctx)
|
|
||||||
) {
|
|
||||||
ShamrockConfig.setInjectPacket(ctx, it)
|
|
||||||
ShamrockConfig.pushUpdate(ctx)
|
|
||||||
return@Function true
|
return@Function true
|
||||||
}
|
}
|
||||||
|
|
||||||
Function(
|
kotlin.runCatching {
|
||||||
title = "自动唤醒QQ",
|
ctx.getSharedPreferences("shared_config", Context.MODE_WORLD_READABLE)
|
||||||
desc = "QQ进程死亡时重新打开QQ进程,前提本进程存活。",
|
}.onSuccess {
|
||||||
descColor = it,
|
Function(
|
||||||
isSwitch = ShamrockConfig.enableAutoStart(ctx)
|
title = LocalString.persistentText,
|
||||||
) {
|
desc = LocalString.persistentTextDesc,
|
||||||
ShamrockConfig.setAutoStart(ctx, it)
|
descColor = color,
|
||||||
return@Function true
|
isSwitch = it.getBoolean("persistent", false)
|
||||||
}
|
) { v ->
|
||||||
|
it.edit().putBoolean("persistent", v).apply()
|
||||||
|
scope.toast(ctx, LocalString.restartSysToast)
|
||||||
|
return@Function true
|
||||||
|
}
|
||||||
|
|
||||||
Function(
|
Function(
|
||||||
title = "开启Shell接口",
|
title = "禁用Doze模式",
|
||||||
desc = "可能导致设备被入侵,请勿随意开启。",
|
desc = "禁止系统进入节能模式。",
|
||||||
descColor = it,
|
descColor = color,
|
||||||
isSwitch = ShamrockConfig.allowShell(ctx)
|
isSwitch = it.getBoolean("hook_doze", false)
|
||||||
) {
|
) { value ->
|
||||||
ShamrockConfig.setShellStatus(ctx, it)
|
it.edit().putBoolean("hook_doze", value).apply()
|
||||||
return@Function true
|
scope.toast(ctx, LocalString.restartSysToast)
|
||||||
|
return@Function true
|
||||||
|
}
|
||||||
|
}.onFailure {
|
||||||
|
AppRuntime.log("无法启用附加选项,LSPosed模块未激活或者不支持XSharedPreferences", Level.WARN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ActionBox(
|
||||||
|
modifier = Modifier.padding(top = 12.dp),
|
||||||
|
painter = painterResource(id = R.drawable.sharp_lock_24),
|
||||||
|
title = "安全性设置"
|
||||||
|
) { color ->
|
||||||
|
Column {
|
||||||
|
Divider(
|
||||||
|
modifier = Modifier,
|
||||||
|
color = GlobalColor.Divider,
|
||||||
|
thickness = 0.2.dp
|
||||||
|
)
|
||||||
|
|
||||||
|
Function(
|
||||||
|
title = LocalString.antiTrace,
|
||||||
|
desc = LocalString.antiTraceDesc,
|
||||||
|
descColor = color,
|
||||||
|
isSwitch = ShamrockConfig[ctx, AntiJvmTrace]
|
||||||
|
) {
|
||||||
|
ShamrockConfig[ctx, AntiJvmTrace] = it
|
||||||
|
scope.toast(ctx, LocalString.restartToast)
|
||||||
|
return@Function true
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin.runCatching {
|
||||||
|
ctx.getSharedPreferences("shared_config", Context.MODE_WORLD_READABLE)
|
||||||
|
}.onSuccess {
|
||||||
|
Function(
|
||||||
|
title = "反检测加强",
|
||||||
|
desc = "可能导致某些设备频繁闪退,将拦截环境包上报。",
|
||||||
|
descColor = color,
|
||||||
|
isSwitch = it.getBoolean("super_anti", false)
|
||||||
|
) { v ->
|
||||||
|
it.edit().putBoolean("super_anti", v).apply()
|
||||||
|
scope.toast(ctx, LocalString.restartToast)
|
||||||
|
return@Function true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ActionBox(
|
ActionBox(
|
||||||
modifier = Modifier.padding(top = 12.dp),
|
modifier = Modifier.padding(top = 12.dp),
|
||||||
painter = painterResource(id = R.drawable.round_logo_dev_24),
|
painter = painterResource(id = R.drawable.round_logo_dev_24),
|
||||||
@ -161,7 +206,11 @@ fun LabFragment() {
|
|||||||
descColor = it,
|
descColor = it,
|
||||||
isSwitch = AppRuntime.state.supportVoice.value
|
isSwitch = AppRuntime.state.supportVoice.value
|
||||||
) {
|
) {
|
||||||
|
if(AppRuntime.state.supportVoice.value) {
|
||||||
|
scope.toast(ctx, "关闭请手动删除文件。")
|
||||||
|
} else {
|
||||||
scope.toast(ctx, "请按照Github提示手动操作。")
|
scope.toast(ctx, "请按照Github提示手动操作。")
|
||||||
|
}
|
||||||
return@Function false
|
return@Function false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,24 +232,23 @@ fun LabFragment() {
|
|||||||
title = "自发消息推送",
|
title = "自发消息推送",
|
||||||
desc = "推送Bot发送的消息,未做特殊处理请勿打开。",
|
desc = "推送Bot发送的消息,未做特殊处理请勿打开。",
|
||||||
descColor = it,
|
descColor = it,
|
||||||
isSwitch = ShamrockConfig.enableSelfMsg(ctx)
|
isSwitch = ShamrockConfig[ctx, EnableSelfMessage]
|
||||||
) {
|
) {
|
||||||
ShamrockConfig.setEnableSelfMsg(ctx, it)
|
ShamrockConfig[ctx, EnableSelfMessage] = it
|
||||||
ShamrockConfig.pushUpdate(ctx)
|
InitHandler.update(ctx)
|
||||||
return@Function true
|
return@Function true
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Function(
|
Function(
|
||||||
title = "使用纯数字ECHO",
|
title = "启用旧版资源上传系统",
|
||||||
desc = "在部分强类型语言框架,需要打开此开关。",
|
desc = "如果NT内核无法上传资源,请打开本开关。",
|
||||||
descColor = it,
|
descColor = it,
|
||||||
isSwitch = ShamrockConfig.isEchoNumber(ctx)
|
isSwitch = ShamrockConfig[ctx, EnableOldBDH]
|
||||||
) {
|
) {
|
||||||
ShamrockConfig.setEchoNumber(ctx, it)
|
ShamrockConfig[ctx, EnableOldBDH] = it
|
||||||
ShamrockConfig.pushUpdate(ctx)
|
InitHandler.update(ctx)
|
||||||
return@Function true
|
return@Function true
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,107 +0,0 @@
|
|||||||
@file:OptIn(DelicateCoroutinesApi::class)
|
|
||||||
package moe.fuqiuluo.shamrock.ui.service
|
|
||||||
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.core.content.ContextCompat.startActivity
|
|
||||||
import io.ktor.client.request.get
|
|
||||||
import io.ktor.client.request.header
|
|
||||||
import io.ktor.client.request.url
|
|
||||||
import io.ktor.client.statement.bodyAsText
|
|
||||||
import io.ktor.http.HttpStatusCode
|
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import moe.fuqiuluo.shamrock.remote.entries.CommonResult
|
|
||||||
import moe.fuqiuluo.shamrock.remote.entries.CurrentAccount
|
|
||||||
import moe.fuqiuluo.shamrock.remote.entries.Status
|
|
||||||
import moe.fuqiuluo.shamrock.tools.GlobalClient
|
|
||||||
import moe.fuqiuluo.shamrock.ui.app.AppRuntime.AccountInfo
|
|
||||||
import moe.fuqiuluo.shamrock.ui.app.AppRuntime.log
|
|
||||||
import moe.fuqiuluo.shamrock.ui.app.AppRuntime.state
|
|
||||||
import moe.fuqiuluo.shamrock.ui.app.Level
|
|
||||||
import moe.fuqiuluo.shamrock.ui.app.ShamrockConfig
|
|
||||||
import moe.fuqiuluo.shamrock.ui.service.internal.broadcastToModule
|
|
||||||
import java.net.ConnectException
|
|
||||||
import java.util.Timer
|
|
||||||
import kotlin.concurrent.timer
|
|
||||||
|
|
||||||
object DashboardInitializer {
|
|
||||||
private var servicePort: Int = 0
|
|
||||||
private lateinit var heartbeatTimer: Timer
|
|
||||||
|
|
||||||
operator fun invoke(context: Context, port: Int) {
|
|
||||||
servicePort = port
|
|
||||||
initHeartbeat(true, context)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initHeartbeat(reload: Boolean, context: Context) {
|
|
||||||
if (::heartbeatTimer.isInitialized && !reload) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (::heartbeatTimer.isInitialized) {
|
|
||||||
heartbeatTimer.cancel()
|
|
||||||
}
|
|
||||||
heartbeatTimer = timer("heartbeat", false, 0, 1000L * 30) {
|
|
||||||
checkService(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkService(context: Context) {
|
|
||||||
GlobalScope.launch {
|
|
||||||
try {
|
|
||||||
GlobalClient.get {
|
|
||||||
url("http://127.0.0.1:$servicePort/get_account_info")
|
|
||||||
val token = ShamrockConfig.getToken(context)
|
|
||||||
if (token.isNotBlank()) {
|
|
||||||
header("Authorization", "Bearer $token")
|
|
||||||
}
|
|
||||||
}.let {
|
|
||||||
if (it.status == HttpStatusCode.OK) {
|
|
||||||
val result: CommonResult<CurrentAccount> = Json.decodeFromString(it.bodyAsText())
|
|
||||||
state.isFined.value = result.retcode == 0
|
|
||||||
if (result.retcode == Status.InternalHandlerError.code) {
|
|
||||||
log("账号未登录。", Level.WARN)
|
|
||||||
} else if (result.retcode != 0) {
|
|
||||||
log("尝试从接口获取账号信息失败,未知错误。", Level.ERROR)
|
|
||||||
} else {
|
|
||||||
AccountInfo.let { account ->
|
|
||||||
account.uin.value = result.data.uin.toString()
|
|
||||||
account.nick.value = result.data.nick
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
state.isFined.value = false
|
|
||||||
log("尝试从接口获取账号信息失败,服务运行异常。", Level.ERROR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: ConnectException) {
|
|
||||||
state.isFined.value = false
|
|
||||||
context.broadcastToModule {
|
|
||||||
putExtra("__cmd", "checkAndStartService")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ShamrockConfig.enableAutoStart(context)) {
|
|
||||||
log("检测到Service死亡,正在尝试重新启动!")
|
|
||||||
GlobalScope.launch(Dispatchers.Main) {
|
|
||||||
val packageName = "com.tencent.mobileqq"
|
|
||||||
val className = "com.tencent.mobileqq.activity.SplashActivity"
|
|
||||||
|
|
||||||
val intent = Intent()
|
|
||||||
intent.component = ComponentName(packageName, className)
|
|
||||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
||||||
intent.putExtra("from", "shamrock")
|
|
||||||
startActivity(context, intent, Bundle.EMPTY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
state.isFined.value = false
|
|
||||||
log(e.stackTraceToString(), Level.ERROR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package moe.fuqiuluo.shamrock.ui.service.handlers
|
|
||||||
|
|
||||||
import android.content.ContentValues
|
|
||||||
import android.content.Context
|
|
||||||
import moe.fuqiuluo.shamrock.ui.app.AppRuntime
|
|
||||||
import moe.fuqiuluo.shamrock.ui.service.DashboardInitializer
|
|
||||||
|
|
||||||
object FetchPortHandler: ModuleHandler() {
|
|
||||||
override val cmd: String = "success"
|
|
||||||
|
|
||||||
override fun onReceive(callbackId: Int, values: ContentValues, context: Context) {
|
|
||||||
AppRuntime.state.supportVoice.value = values.getAsBoolean("voice")
|
|
||||||
DashboardInitializer(context, values.getAsInteger("port"))
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,13 +3,37 @@ package moe.fuqiuluo.shamrock.ui.service.handlers
|
|||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import moe.fuqiuluo.shamrock.ui.app.AppRuntime
|
import moe.fuqiuluo.shamrock.ui.app.AppRuntime
|
||||||
import moe.fuqiuluo.shamrock.ui.app.ShamrockConfig
|
import moe.fuqiuluo.shamrock.app.config.ShamrockConfig
|
||||||
|
import moe.fuqiuluo.shamrock.config.*
|
||||||
|
|
||||||
internal object InitHandler: ModuleHandler() {
|
internal object InitHandler: ModuleHandler() {
|
||||||
override val cmd: String = "init"
|
override val cmd: String = "init"
|
||||||
|
|
||||||
override fun onReceive(callbackId: Int, values: ContentValues, context: Context) {
|
override fun onReceive(callbackId: Int, values: ContentValues, context: Context) {
|
||||||
|
update(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(context: Context) {
|
||||||
AppRuntime.log("推送QQ进程初始化设置数据包成功...")
|
AppRuntime.log("推送QQ进程初始化设置数据包成功...")
|
||||||
callback(context, callbackId, ShamrockConfig.getConfigMap(context))
|
|
||||||
|
val maps = hashMapOf<String, Any?>()
|
||||||
|
|
||||||
|
ActiveRPC.update(context, maps)
|
||||||
|
AliveReply.update(context, maps)
|
||||||
|
AntiJvmTrace.update(context, maps)
|
||||||
|
DebugMode.update(context, maps)
|
||||||
|
EnableOldBDH.update(context, maps)
|
||||||
|
EnableSelfMessage.update(context, maps)
|
||||||
|
ForceTablet.update(context, maps)
|
||||||
|
PassiveRPC.update(context, maps)
|
||||||
|
ResourceGroup.update(context, maps)
|
||||||
|
RPCAddress.update(context, maps)
|
||||||
|
RPCPort.update(context, maps)
|
||||||
|
|
||||||
|
callback(context, 1, maps)
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T> ConfigKey<T>.update(context: Context, map: HashMap<String, Any?>) {
|
||||||
|
map[name()] = ShamrockConfig[context, this]
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -29,6 +29,7 @@ abstract class ModuleHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
putExtra("__cmd", cmd)
|
||||||
putExtra("__hash", callbackId)
|
putExtra("__hash", callbackId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
package moe.fuqiuluo.shamrock.ui.service.handlers
|
||||||
|
|
||||||
|
import android.content.ContentValues
|
||||||
|
import android.content.Context
|
||||||
|
import android.widget.Toast
|
||||||
|
import moe.fuqiuluo.shamrock.tools.GlobalUi
|
||||||
|
import moe.fuqiuluo.shamrock.ui.app.AppRuntime
|
||||||
|
import java.util.Timer
|
||||||
|
import kotlin.concurrent.timer
|
||||||
|
import kotlin.concurrent.timerTask
|
||||||
|
|
||||||
|
object SwitchStatus: ModuleHandler() {
|
||||||
|
override val cmd: String
|
||||||
|
get() = "switch_status"
|
||||||
|
|
||||||
|
private var lastActiveTime = 0L
|
||||||
|
private var timer: Timer? = null
|
||||||
|
|
||||||
|
override fun onReceive(callbackId: Int, values: ContentValues, context: Context) {
|
||||||
|
val voiceSwitch = values.getAsBoolean("voice")
|
||||||
|
val nickname = values.getAsString("nickname")
|
||||||
|
val account = values.getAsString("account")
|
||||||
|
if (lastActiveTime == 0L) GlobalUi.post {
|
||||||
|
Toast.makeText(context, "激活成功", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
AppRuntime.state.apply {
|
||||||
|
isFined.value = true
|
||||||
|
coreVersion.value = values.getAsString("core_version")
|
||||||
|
coreName.value = "LSPosed"
|
||||||
|
supportVoice.value = voiceSwitch
|
||||||
|
}
|
||||||
|
AppRuntime.AccountInfo.apply {
|
||||||
|
uin.value = account
|
||||||
|
nick.value = nickname
|
||||||
|
}
|
||||||
|
lastActiveTime = System.currentTimeMillis()
|
||||||
|
startTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startTimer() {
|
||||||
|
timer?.cancel()
|
||||||
|
timer = timer("SwitchStatus", true, 0, 5_000) {
|
||||||
|
if (lastActiveTime != 0L && System.currentTimeMillis() - lastActiveTime > 30 * 1000) {
|
||||||
|
AppRuntime.state.isFined.value = false
|
||||||
|
lastActiveTime = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,9 +5,9 @@ import android.content.ContentValues
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.net.Uri
|
|
||||||
import moe.fuqiuluo.shamrock.ui.service.ModuleTalker
|
import moe.fuqiuluo.shamrock.ui.service.ModuleTalker
|
||||||
import moe.fuqiuluo.shamrock.ui.service.handlers.*
|
import moe.fuqiuluo.shamrock.ui.service.handlers.*
|
||||||
|
import android.net.Uri
|
||||||
|
|
||||||
class MultifunctionalProvider: ContentProvider() {
|
class MultifunctionalProvider: ContentProvider() {
|
||||||
override fun insert(uri: Uri, content: ContentValues?): Uri {
|
override fun insert(uri: Uri, content: ContentValues?): Uri {
|
||||||
@ -28,8 +28,8 @@ class MultifunctionalProvider: ContentProvider() {
|
|||||||
|
|
||||||
override fun onCreate(): Boolean {
|
override fun onCreate(): Boolean {
|
||||||
ModuleTalker.register(InitHandler)
|
ModuleTalker.register(InitHandler)
|
||||||
ModuleTalker.register(FetchPortHandler)
|
|
||||||
ModuleTalker.register(LogHandler)
|
ModuleTalker.register(LogHandler)
|
||||||
|
ModuleTalker.register(SwitchStatus)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ class MultifunctionalProvider: ContentProvider() {
|
|||||||
|
|
||||||
inline fun Context.broadcastToModule(intentBuilder: Intent.() -> Unit) {
|
inline fun Context.broadcastToModule(intentBuilder: Intent.() -> Unit) {
|
||||||
val intent = Intent()
|
val intent = Intent()
|
||||||
intent.action = "moe.fuqiuluo.xqbot.dynamic"
|
intent.action = "moe.fuqiuluo.kritor.dynamic"
|
||||||
intent.intentBuilder()
|
intent.intentBuilder()
|
||||||
sendBroadcast(intent)
|
sendBroadcast(intent)
|
||||||
}
|
}
|
@ -6,7 +6,9 @@ package moe.fuqiuluo.shamrock.ui.theme
|
|||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.ReadOnlyComposable
|
import androidx.compose.runtime.ReadOnlyComposable
|
||||||
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import moe.fuqiuluo.shamrock.R
|
import moe.fuqiuluo.shamrock.R
|
||||||
|
|
||||||
private val LocalStringDefault = Default()
|
private val LocalStringDefault = Default()
|
||||||
@ -69,6 +71,24 @@ private open class Chūnibyō: Default() {
|
|||||||
"执明起,至除免于灾祸。\n" +
|
"执明起,至除免于灾祸。\n" +
|
||||||
"元冥浩浩,非凡不可动之。"
|
"元冥浩浩,非凡不可动之。"
|
||||||
labWarning = "寒酥降矣,梅熟日久,莫不可测。"
|
labWarning = "寒酥降矣,梅熟日久,莫不可测。"
|
||||||
|
logTitle = "无极"
|
||||||
|
testName = "未名之人"
|
||||||
|
logCentralLoadSuccessfully = "无极开,天地始纷争。"
|
||||||
|
logCentralLoadFailed = "无极闭,天地始归宁。"
|
||||||
|
functionSetting = "天地法则"
|
||||||
|
sslSetting = "天行御令"
|
||||||
|
warnTitle = "仙人指路"
|
||||||
|
b2Mode = "通仙之路"
|
||||||
|
b2ModeDesc = "凡人勿近"
|
||||||
|
restartToast = "复关喏哉!"
|
||||||
|
showDebugLog = "窥探天机"
|
||||||
|
showDebugLogDesc = "迷失自我,走火入魔"
|
||||||
|
antiTrace = "鬼影迷踪"
|
||||||
|
antiTraceDesc = "唐门绝学,已有取死之道"
|
||||||
|
injectPacket = "遮匿无用之禀"
|
||||||
|
injectPacketDesc = "试于试之,逆则魂飞魄散"
|
||||||
|
persistentText = "丹书铁券"
|
||||||
|
persistentTextDesc = "由天地之起也,须复动之。"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +104,25 @@ private open class Default: VarString(
|
|||||||
"同时声明本项目仅用于学习与交流,请于24小时内删除。\n" +
|
"同时声明本项目仅用于学习与交流,请于24小时内删除。\n" +
|
||||||
"同时开源贡献者均享受免责条例。",
|
"同时开源贡献者均享受免责条例。",
|
||||||
labWarning = "实验室功能,可能会导致出乎意料的BUG!",
|
labWarning = "实验室功能,可能会导致出乎意料的BUG!",
|
||||||
"日志"
|
logTitle = "日志",
|
||||||
|
testName = "测试昵称",
|
||||||
|
logCentralLoadSuccessfully = "日志框架激活成功,开放操作许可。",
|
||||||
|
logCentralLoadFailed = "日志框架处于未激活状态,请检查。",
|
||||||
|
functionSetting = "功能设置",
|
||||||
|
sslSetting = "SSL配置",
|
||||||
|
warnTitle = "温馨提示",
|
||||||
|
b2Mode = "中二病模式",
|
||||||
|
b2ModeDesc = "也许会导致奇怪的问题,大抵就是你看不懂罢了。",
|
||||||
|
restartToast = "重启生效哦!",
|
||||||
|
restartSysToast = "重启系统生效哦!",
|
||||||
|
showDebugLog = "显示调试日志",
|
||||||
|
showDebugLogDesc = "会导致日志刷屏。",
|
||||||
|
antiTrace = "防止调用栈检测",
|
||||||
|
antiTraceDesc = "防止QQ进行堆栈跟踪检测,需要重新启动QQ。",
|
||||||
|
injectPacket = "拦截QQ无用收包",
|
||||||
|
injectPacketDesc = "测试阶段,可能导致网络异常或掉线。",
|
||||||
|
persistentText = "免死金牌",
|
||||||
|
persistentTextDesc = "由系统复活QQ和Shamrock,需要重新启动系统。"
|
||||||
)
|
)
|
||||||
|
|
||||||
open class VarString(
|
open class VarString(
|
||||||
@ -99,5 +137,43 @@ open class VarString(
|
|||||||
|
|
||||||
var labWarning: String,
|
var labWarning: String,
|
||||||
|
|
||||||
var logTitle: String
|
var logTitle: String,
|
||||||
)
|
|
||||||
|
var testName: String,
|
||||||
|
|
||||||
|
var logCentralLoadSuccessfully: String,
|
||||||
|
var logCentralLoadFailed: String,
|
||||||
|
|
||||||
|
var functionSetting: String,
|
||||||
|
var sslSetting: String,
|
||||||
|
|
||||||
|
var warnTitle: String,
|
||||||
|
|
||||||
|
var b2Mode: String,
|
||||||
|
var b2ModeDesc: String,
|
||||||
|
|
||||||
|
var restartToast: String,
|
||||||
|
var restartSysToast: String,
|
||||||
|
|
||||||
|
var showDebugLog: String,
|
||||||
|
var showDebugLogDesc: String,
|
||||||
|
|
||||||
|
var antiTrace: String,
|
||||||
|
var antiTraceDesc: String,
|
||||||
|
|
||||||
|
var injectPacket: String,
|
||||||
|
var injectPacketDesc: String,
|
||||||
|
|
||||||
|
var persistentText: String,
|
||||||
|
var persistentTextDesc: String
|
||||||
|
) {
|
||||||
|
private var inited = false
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun init(): VarString {
|
||||||
|
if (inited) return this
|
||||||
|
|
||||||
|
inited = true
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,23 +1,35 @@
|
|||||||
package moe.fuqiuluo.shamrock.ui.tools
|
package moe.fuqiuluo.shamrock.ui.tools
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.animateColor
|
import androidx.compose.animation.animateColor
|
||||||
|
import androidx.compose.animation.core.FastOutLinearInEasing
|
||||||
|
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||||
import androidx.compose.animation.core.LinearEasing
|
import androidx.compose.animation.core.LinearEasing
|
||||||
|
import androidx.compose.animation.core.MutableTransitionState
|
||||||
|
import androidx.compose.animation.core.TweenSpec
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.animation.core.updateTransition
|
import androidx.compose.animation.core.updateTransition
|
||||||
|
import androidx.compose.animation.scaleIn
|
||||||
|
import androidx.compose.animation.scaleOut
|
||||||
import androidx.compose.foundation.Indication
|
import androidx.compose.foundation.Indication
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.indication
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.selection.selectable
|
import androidx.compose.foundation.selection.selectable
|
||||||
import androidx.compose.material.ripple.rememberRipple
|
import androidx.compose.material.ripple.rememberRipple
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.LocalContentColor
|
import androidx.compose.material3.LocalContentColor
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.ProvideTextStyle
|
import androidx.compose.material3.ProvideTextStyle
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.Typography
|
import androidx.compose.material3.Typography
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
@ -31,8 +43,10 @@ import androidx.compose.ui.layout.LastBaseline
|
|||||||
import androidx.compose.ui.layout.Layout
|
import androidx.compose.ui.layout.Layout
|
||||||
import androidx.compose.ui.layout.Placeable
|
import androidx.compose.ui.layout.Placeable
|
||||||
import androidx.compose.ui.layout.layoutId
|
import androidx.compose.ui.layout.layoutId
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.semantics.Role
|
import androidx.compose.ui.semantics.Role
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.Density
|
import androidx.compose.ui.unit.Density
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@ -135,20 +149,18 @@ private fun TabBaselineLayout(
|
|||||||
text: @Composable (() -> Unit)?,
|
text: @Composable (() -> Unit)?,
|
||||||
icon: @Composable (() -> Unit)?
|
icon: @Composable (() -> Unit)?
|
||||||
) {
|
) {
|
||||||
Layout(
|
Layout({
|
||||||
{
|
if (text != null) {
|
||||||
if (text != null) {
|
Box(
|
||||||
Box(
|
Modifier
|
||||||
Modifier
|
.layoutId("text")
|
||||||
.layoutId("text")
|
.padding(horizontal = HorizontalTextPadding)
|
||||||
.padding(horizontal = HorizontalTextPadding)
|
) { text() }
|
||||||
) { text() }
|
|
||||||
}
|
|
||||||
if (icon != null) {
|
|
||||||
Box(Modifier.layoutId("icon")) { icon() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
) { measurables, constraints ->
|
if (icon != null) {
|
||||||
|
Box(Modifier.layoutId("icon")) { icon() }
|
||||||
|
}
|
||||||
|
}) { measurables, constraints ->
|
||||||
val textPlaceable = text?.let {
|
val textPlaceable = text?.let {
|
||||||
measurables.first { it.layoutId == "text" }.measure(
|
measurables.first { it.layoutId == "text" }.measure(
|
||||||
// Measure with loose constraints for height as we don't want the text to take up more
|
// Measure with loose constraints for height as we don't want the text to take up more
|
||||||
@ -247,21 +259,66 @@ fun ShamrockTab(
|
|||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
text: @Composable (() -> Unit)? = null,
|
|
||||||
icon: @Composable (() -> Unit)? = null,
|
|
||||||
selectedContentColor: Color = GlobalColor.TabSelected,
|
selectedContentColor: Color = GlobalColor.TabSelected,
|
||||||
unselectedContentColor: Color = selectedContentColor,
|
unselectedContentColor: Color = selectedContentColor,
|
||||||
indication: Indication? = rememberRipple(bounded = true, color = selectedContentColor),
|
indication: Indication? = rememberRipple(bounded = true, color = selectedContentColor),
|
||||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||||
|
titleWithIcon: Pair<String, Int>,
|
||||||
|
visibleState: MutableTransitionState<Boolean>
|
||||||
) {
|
) {
|
||||||
val styledText: @Composable (() -> Unit)? = text?.let {
|
var text: @Composable (() -> Unit)? = null
|
||||||
@Composable {
|
var icon: @Composable (() -> Unit)? = null
|
||||||
val style =
|
|
||||||
MaterialTheme.typography.fromToken(PrimaryNavigationTabTokens.LabelTextFont)
|
if (!selected) {
|
||||||
.copy(textAlign = TextAlign.Center)
|
icon = {
|
||||||
ProvideTextStyle(style, content = text)
|
Icon(
|
||||||
|
painter = painterResource(id = titleWithIcon.second),
|
||||||
|
contentDescription = titleWithIcon.first,
|
||||||
|
tint = Color.Unspecified,
|
||||||
|
modifier = Modifier
|
||||||
|
.height(24.dp)
|
||||||
|
.width(24.dp)
|
||||||
|
.padding(bottom = 5.dp)
|
||||||
|
.indication(
|
||||||
|
remember { MutableInteractionSource() },
|
||||||
|
rememberRipple(color = Color.Transparent)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text = {
|
||||||
|
val style = MaterialTheme.typography
|
||||||
|
.fromToken(PrimaryNavigationTabTokens.LabelTextFont)
|
||||||
|
.copy(textAlign = TextAlign.Center)
|
||||||
|
|
||||||
|
ProvideTextStyle(style) {
|
||||||
|
AnimatedVisibility(
|
||||||
|
visibleState = visibleState,
|
||||||
|
enter = remember {
|
||||||
|
scaleIn(animationSpec = TweenSpec(150, easing = FastOutLinearInEasing))
|
||||||
|
},
|
||||||
|
exit = remember {
|
||||||
|
scaleOut(animationSpec = TweenSpec(150, easing = FastOutSlowInEasing))
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = titleWithIcon.first,
|
||||||
|
color = GlobalColor.TabItem,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(bottom = 5.dp)
|
||||||
|
.indication(
|
||||||
|
remember { MutableInteractionSource() },
|
||||||
|
rememberRipple(color = Color.Transparent)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShamrockTab(
|
ShamrockTab(
|
||||||
selected,
|
selected,
|
||||||
onClick,
|
onClick,
|
||||||
@ -272,7 +329,10 @@ fun ShamrockTab(
|
|||||||
interactionSource,
|
interactionSource,
|
||||||
indication
|
indication
|
||||||
) {
|
) {
|
||||||
TabBaselineLayout(icon = icon, text = styledText)
|
TabBaselineLayout(
|
||||||
|
icon = icon,
|
||||||
|
text = text
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
app/src/main/res/drawable/sharp_lock_24.xml
Normal file
5
app/src/main/res/drawable/sharp_lock_24.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#9D9D9D"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M20,8h-3L17,6.21c0,-2.61 -1.91,-4.94 -4.51,-5.19C9.51,0.74 7,3.08 7,6v2L4,8v14h16L20,8zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM9,8L9,6c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2L9,8z"/>
|
||||||
|
</vector>
|
@ -2,16 +2,14 @@ package moe.fuqiuluo.shamrock
|
|||||||
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
*
|
*
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
*/
|
*/
|
||||||
class ExampleUnitTest {
|
class ExampleUnitTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun addition_isCorrect() {
|
fun test() {
|
||||||
assertEquals(4, 2 + 2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,6 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application") version "8.1.2" apply false
|
id("com.android.application") version "8.2.0" apply false
|
||||||
id("org.jetbrains.kotlin.android") version "1.8.10" apply false
|
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
|
||||||
id("com.android.library") version "8.1.2" apply false
|
id("com.android.library") version "8.2.0" apply false
|
||||||
//id("io.realm.kotlin") version "1.11.0" apply false
|
|
||||||
}
|
}
|
10
buildSrc/build.gradle.kts
Normal file
10
buildSrc/build.gradle.kts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm") version "1.9.22"
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
}
|
23
buildSrc/src/main/kotlin/Dependencies.kt
Normal file
23
buildSrc/src/main/kotlin/Dependencies.kt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
val DEPENDENCY_ANDROIDX = arrayOf(
|
||||||
|
"androidx.core:core-ktx:1.12.0",
|
||||||
|
"androidx.appcompat:appcompat:1.6.1",
|
||||||
|
"com.google.android.material:material:1.11.0",
|
||||||
|
"androidx.exifinterface:exifinterface:1.3.7",
|
||||||
|
"androidx.lifecycle:lifecycle-runtime-ktx:2.6.1",
|
||||||
|
"androidx.activity:activity-compose:1.7.2",
|
||||||
|
)
|
||||||
|
|
||||||
|
fun room(name: String) = "androidx.room:room-$name:${Versions.roomVersion}"
|
||||||
|
|
||||||
|
fun kotlinx(name: String, version: String) = "org.jetbrains.kotlinx:kotlinx-$name:$version"
|
||||||
|
|
||||||
|
fun ktor(target: String, name: String): String {
|
||||||
|
return "io.ktor:ktor-$target-$name:${Versions.ktorVersion}"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun grpc(name: String, version: String) = "io.grpc:grpc-$name:$version"
|
||||||
|
|
||||||
|
object Versions {
|
||||||
|
const val roomVersion = "2.5.0"
|
||||||
|
const val ktorVersion = "2.3.3"
|
||||||
|
}
|
@ -22,3 +22,5 @@ kotlin.code.style=official
|
|||||||
# thereby reducing the size of the R class for that library
|
# thereby reducing the size of the R class for that library
|
||||||
android.nonTransitiveRClass=true
|
android.nonTransitiveRClass=true
|
||||||
android.default.buildFeatures.aidl=true
|
android.default.buildFeatures.aidl=true
|
||||||
|
kotlin.experimental.tryK2=true
|
||||||
|
ksp.incremental=false
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
3
gradlew
vendored
3
gradlew
vendored
@ -83,7 +83,8 @@ done
|
|||||||
# This is normally unused
|
# This is normally unused
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
|
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
|
42
kritor/.gitignore
vendored
Normal file
42
kritor/.gitignore
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
.gradle
|
||||||
|
build/
|
||||||
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
out/
|
||||||
|
!**/src/main/**/out/
|
||||||
|
!**/src/test/**/out/
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
bin/
|
||||||
|
!**/src/main/**/bin/
|
||||||
|
!**/src/test/**/bin/
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
76
kritor/build.gradle.kts
Normal file
76
kritor/build.gradle.kts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("com.android.library")
|
||||||
|
id("org.jetbrains.kotlin.android")
|
||||||
|
id("com.google.protobuf") version "0.9.4"
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "moe.whitechi73.kritor"
|
||||||
|
compileSdk = 34
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk = 24
|
||||||
|
|
||||||
|
consumerProguardFiles("consumer-rules.pro")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
protobuf(files("kritor/protos"))
|
||||||
|
|
||||||
|
implementation("com.google.protobuf:protobuf-java:4.26.0")
|
||||||
|
|
||||||
|
implementation(kotlinx("coroutines-core", "1.8.0"))
|
||||||
|
|
||||||
|
implementation(grpc("stub", "1.62.2"))
|
||||||
|
implementation(grpc("protobuf", "1.62.2"))
|
||||||
|
implementation(grpc("kotlin-stub", "1.4.1"))
|
||||||
|
}
|
||||||
|
|
||||||
|
protobuf {
|
||||||
|
protoc {
|
||||||
|
artifact = "com.google.protobuf:protoc:4.26.0"
|
||||||
|
}
|
||||||
|
plugins {
|
||||||
|
create("grpc") {
|
||||||
|
artifact = "io.grpc:protoc-gen-grpc-java:1.62.2"
|
||||||
|
}
|
||||||
|
create("grpckt") {
|
||||||
|
artifact = "io.grpc:protoc-gen-grpc-kotlin:1.4.1:jdk8@jar"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
generateProtoTasks {
|
||||||
|
all().forEach {
|
||||||
|
it.plugins {
|
||||||
|
create("grpc")
|
||||||
|
create("grpckt")
|
||||||
|
}
|
||||||
|
it.builtins {
|
||||||
|
create("java")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<KotlinCompile>().configureEach {
|
||||||
|
kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
|
||||||
|
}
|
0
kritor/consumer-rules.pro
Normal file
0
kritor/consumer-rules.pro
Normal file
1
kritor/kritor
Submodule
1
kritor/kritor
Submodule
Submodule kritor/kritor added at 27669a8f57
21
kritor/proguard-rules.pro
vendored
Normal file
21
kritor/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
1
processor/.gitignore
vendored
Normal file
1
processor/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build
|
22
processor/build.gradle.kts
Normal file
22
processor/build.gradle.kts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
id("com.google.devtools.ksp") version "1.9.22-1.0.17"
|
||||||
|
kotlin("plugin.serialization") version "1.9.22"
|
||||||
|
}
|
||||||
|
|
||||||
|
ksp {
|
||||||
|
arg("autoserviceKsp.verify", "true")
|
||||||
|
arg("autoserviceKsp.verbose", "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":annotations"))
|
||||||
|
implementation("com.google.auto.service:auto-service-annotations:1.1.1")
|
||||||
|
implementation("com.google.devtools.ksp:symbol-processing-api:1.9.21-1.0.15")
|
||||||
|
implementation("com.squareup:kotlinpoet:1.14.2")
|
||||||
|
|
||||||
|
//implementation(DEPENDENCY_PROTOBUF)
|
||||||
|
implementation(kotlinx("serialization-protobuf", "1.6.2"))
|
||||||
|
|
||||||
|
ksp("dev.zacsweers.autoservice:auto-service-ksp:1.1.0")
|
||||||
|
}
|
0
processor/consumer-rules.pro
Normal file
0
processor/consumer-rules.pro
Normal file
21
processor/proguard-rules.pro
vendored
Normal file
21
processor/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
4
processor/src/main/AndroidManifest.xml
Normal file
4
processor/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
</manifest>
|
@ -0,0 +1,83 @@
|
|||||||
|
@file:Suppress("UNCHECKED_CAST")
|
||||||
|
@file:OptIn(KspExperimental::class)
|
||||||
|
|
||||||
|
package moe.fuqiuluo.ksp.impl
|
||||||
|
|
||||||
|
import com.google.devtools.ksp.KspExperimental
|
||||||
|
import com.google.devtools.ksp.getAnnotationsByType
|
||||||
|
import com.google.devtools.ksp.processing.*
|
||||||
|
import com.google.devtools.ksp.symbol.KSAnnotated
|
||||||
|
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
|
||||||
|
import com.squareup.kotlinpoet.FileSpec
|
||||||
|
import com.squareup.kotlinpoet.FunSpec
|
||||||
|
import com.squareup.kotlinpoet.KModifier
|
||||||
|
import kritor.service.Grpc
|
||||||
|
|
||||||
|
class GrpcProcessor(
|
||||||
|
private val codeGenerator: CodeGenerator,
|
||||||
|
private val logger: KSPLogger
|
||||||
|
): SymbolProcessor {
|
||||||
|
override fun process(resolver: Resolver): List<KSAnnotated> {
|
||||||
|
val symbols = resolver.getSymbolsWithAnnotation(Grpc::class.qualifiedName!!)
|
||||||
|
val actions = (symbols as Sequence<KSFunctionDeclaration>).toList()
|
||||||
|
|
||||||
|
if (actions.isEmpty()) return emptyList()
|
||||||
|
|
||||||
|
// 怎么返回nullable的结果
|
||||||
|
val packageName = "kritor.handlers"
|
||||||
|
val funcBuilder = FunSpec.builder("handleGrpc")
|
||||||
|
.addModifiers(KModifier.SUSPEND)
|
||||||
|
.addParameter("cmd", String::class)
|
||||||
|
.addParameter("data", ByteArray::class)
|
||||||
|
.returns(ByteArray::class)
|
||||||
|
val fileSpec = FileSpec.scriptBuilder("AutoGrpcHandlers", packageName)
|
||||||
|
|
||||||
|
logger.warn("Found ${actions.size} grpc-actions")
|
||||||
|
|
||||||
|
//logger.error(resolver.getClassDeclarationByName("io.kritor.AuthReq").toString())
|
||||||
|
//logger.error(resolver.getJavaClassByName("io.kritor.AuthReq").toString())
|
||||||
|
//logger.error(resolver.getKotlinClassByName("io.kritor.AuthReq").toString())
|
||||||
|
|
||||||
|
actions.forEach { action ->
|
||||||
|
val methodName = action.qualifiedName?.asString()!!
|
||||||
|
val grpcMethod = action.getAnnotationsByType(Grpc::class).first()
|
||||||
|
val service = grpcMethod.serviceName
|
||||||
|
val funcName = grpcMethod.funcName
|
||||||
|
funcBuilder.addStatement("if (cmd == \"${service}.${funcName}\") {\t")
|
||||||
|
|
||||||
|
val reqType = action.parameters[0].type.toString()
|
||||||
|
val rspType = action.returnType.toString()
|
||||||
|
funcBuilder.addStatement("val resp: $rspType = $methodName($reqType.parseFrom(data))")
|
||||||
|
funcBuilder.addStatement("return resp.toByteArray()")
|
||||||
|
|
||||||
|
funcBuilder.addStatement("}")
|
||||||
|
}
|
||||||
|
funcBuilder.addStatement("return EMPTY_BYTE_ARRAY")
|
||||||
|
fileSpec
|
||||||
|
.addStatement("import io.kritor.authentication.*")
|
||||||
|
.addStatement("import io.kritor.core.*")
|
||||||
|
.addStatement("import io.kritor.customization.*")
|
||||||
|
.addStatement("import io.kritor.developer.*")
|
||||||
|
.addStatement("import io.kritor.file.*")
|
||||||
|
.addStatement("import io.kritor.friend.*")
|
||||||
|
.addStatement("import io.kritor.group.*")
|
||||||
|
.addStatement("import io.kritor.guild.*")
|
||||||
|
.addStatement("import io.kritor.message.*")
|
||||||
|
.addStatement("import io.kritor.web.*")
|
||||||
|
.addFunction(funcBuilder.build())
|
||||||
|
.addImport("moe.fuqiuluo.symbols", "EMPTY_BYTE_ARRAY")
|
||||||
|
runCatching {
|
||||||
|
codeGenerator.createNewFile(
|
||||||
|
dependencies = Dependencies(aggregating = false),
|
||||||
|
packageName = packageName,
|
||||||
|
fileName = fileSpec.name
|
||||||
|
).use { outputStream ->
|
||||||
|
outputStream.writer().use {
|
||||||
|
fileSpec.build().writeTo(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
@file:Suppress("UNCHECKED_CAST")
|
||||||
|
package moe.fuqiuluo.ksp.impl
|
||||||
|
|
||||||
|
import com.google.devtools.ksp.isInternal
|
||||||
|
import com.google.devtools.ksp.isPrivate
|
||||||
|
import com.google.devtools.ksp.processing.CodeGenerator
|
||||||
|
import com.google.devtools.ksp.processing.Dependencies
|
||||||
|
import com.google.devtools.ksp.processing.KSPLogger
|
||||||
|
import com.google.devtools.ksp.processing.Resolver
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessor
|
||||||
|
import com.google.devtools.ksp.symbol.ClassKind
|
||||||
|
import com.google.devtools.ksp.symbol.KSAnnotated
|
||||||
|
import com.google.devtools.ksp.symbol.KSClassDeclaration
|
||||||
|
import com.google.devtools.ksp.symbol.KSDeclaration
|
||||||
|
import com.google.devtools.ksp.validate
|
||||||
|
import com.squareup.kotlinpoet.FileSpec
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
class ProtobufProcessor(
|
||||||
|
private val codeGenerator: CodeGenerator,
|
||||||
|
private val logger: KSPLogger
|
||||||
|
): SymbolProcessor {
|
||||||
|
override fun process(resolver: Resolver): List<KSAnnotated> {
|
||||||
|
val symbols = resolver.getSymbolsWithAnnotation(Serializable::class.qualifiedName!!)
|
||||||
|
val unableToProcess = symbols.filterNot { it.validate() }
|
||||||
|
val actions = (symbols.filter {
|
||||||
|
it is KSClassDeclaration && it.validate() && it.classKind == ClassKind.CLASS
|
||||||
|
} as Sequence<KSClassDeclaration>).filter {
|
||||||
|
it.superTypes.any { superType ->
|
||||||
|
superType.resolve().declaration.qualifiedName?.asString() == "moe.fuqiuluo.symbols.Protobuf"
|
||||||
|
}
|
||||||
|
}.toList()
|
||||||
|
|
||||||
|
if (actions.isNotEmpty()) {
|
||||||
|
actions.forEachIndexed { _, clz ->
|
||||||
|
if (clz.isInternal()) return@forEachIndexed
|
||||||
|
if (clz.isPrivate()) return@forEachIndexed
|
||||||
|
|
||||||
|
val packageName = "protobuf.auto"
|
||||||
|
val fileSpecBuilder = FileSpec.scriptBuilder("FastProtobuf", packageName)
|
||||||
|
|
||||||
|
fileSpecBuilder.addImport("kotlinx.serialization.protobuf", "ProtoBuf")
|
||||||
|
fileSpecBuilder.addImport("kotlinx.serialization", "decodeFromByteArray")
|
||||||
|
fileSpecBuilder.addImport("kotlinx.serialization", "encodeToByteArray")
|
||||||
|
|
||||||
|
if (clz.parentDeclaration != null) {
|
||||||
|
fileSpecBuilder.addImport(clz.importPackage, clz.simpleName.asString())
|
||||||
|
} else {
|
||||||
|
fileSpecBuilder.addImport(clz.packageName.asString(), clz.simpleName.asString())
|
||||||
|
}
|
||||||
|
if (clz.typeParameters.isNotEmpty()) {
|
||||||
|
val genericType = clz.typeParameters.joinToString(", ") { it.name.asString() }
|
||||||
|
fileSpecBuilder.addStatement("""inline fun <$genericType> ${clz.simpleName.asString()}<$genericType>.toByteArray() = ProtoBuf.encodeToByteArray(this)""")
|
||||||
|
} else {
|
||||||
|
fileSpecBuilder.addStatement("inline fun ${clz.simpleName.asString()}.toByteArray() = ProtoBuf.encodeToByteArray(this)")
|
||||||
|
}
|
||||||
|
|
||||||
|
codeGenerator.createNewFile(
|
||||||
|
dependencies = Dependencies.ALL_FILES,
|
||||||
|
packageName = packageName,
|
||||||
|
fileName = "FP${clz.simpleName.asString().hashCode()}"
|
||||||
|
).use { outputStream ->
|
||||||
|
outputStream.writer().use {
|
||||||
|
fileSpecBuilder.build().writeTo(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unableToProcess.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val KSDeclaration.importPackage: String
|
||||||
|
get() = if (parentDeclaration != null) {
|
||||||
|
parentDeclaration!!.importPackage + "." + parentDeclaration!!.simpleName.asString()
|
||||||
|
} else packageName.asString()
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
@file:Suppress("UNCHECKED_CAST", "LocalVariableName", "PrivatePropertyName")
|
||||||
|
@file:OptIn(KspExperimental::class, KspExperimental::class)
|
||||||
|
|
||||||
|
package moe.fuqiuluo.ksp.impl
|
||||||
|
|
||||||
|
import com.google.devtools.ksp.KspExperimental
|
||||||
|
import com.google.devtools.ksp.getAnnotationsByType
|
||||||
|
import com.google.devtools.ksp.getClassDeclarationByName
|
||||||
|
import com.google.devtools.ksp.processing.CodeGenerator
|
||||||
|
import com.google.devtools.ksp.processing.Dependencies
|
||||||
|
import com.google.devtools.ksp.processing.KSPLogger
|
||||||
|
import com.google.devtools.ksp.processing.Resolver
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessor
|
||||||
|
import com.google.devtools.ksp.symbol.ClassKind
|
||||||
|
import com.google.devtools.ksp.symbol.KSAnnotated
|
||||||
|
import com.google.devtools.ksp.symbol.KSClassDeclaration
|
||||||
|
import com.google.devtools.ksp.symbol.KSVisitorVoid
|
||||||
|
import com.google.devtools.ksp.validate
|
||||||
|
import com.squareup.kotlinpoet.ClassName
|
||||||
|
import com.squareup.kotlinpoet.FileSpec
|
||||||
|
import com.squareup.kotlinpoet.FunSpec
|
||||||
|
import moe.fuqiuluo.symbols.Process
|
||||||
|
import moe.fuqiuluo.symbols.XposedHook
|
||||||
|
|
||||||
|
class XposedHookProcessor(
|
||||||
|
private val codeGenerator: CodeGenerator,
|
||||||
|
private val logger: KSPLogger
|
||||||
|
): SymbolProcessor {
|
||||||
|
override fun process(resolver: Resolver): List<KSAnnotated> {
|
||||||
|
val symbols = resolver.getSymbolsWithAnnotation(
|
||||||
|
annotationName = XposedHook::class.qualifiedName!!,
|
||||||
|
inDepth = true
|
||||||
|
)
|
||||||
|
logger.warn("Found ${symbols.count()} classes annotated with XposedHook")
|
||||||
|
val unableToProcess = symbols.filterNot { it.validate() }
|
||||||
|
val actions = (symbols.filter {
|
||||||
|
it is KSClassDeclaration && it.classKind == ClassKind.CLASS
|
||||||
|
} as Sequence<KSClassDeclaration>).toList()
|
||||||
|
|
||||||
|
if (actions.isNotEmpty()) {
|
||||||
|
val firstActions = arrayListOf<KSClassDeclaration>()
|
||||||
|
val serviceActions = arrayListOf<KSClassDeclaration>()
|
||||||
|
actions.forEach {
|
||||||
|
val priority = it.getAnnotationsByType(XposedHook::class).first().priority
|
||||||
|
if (priority >= 10) {
|
||||||
|
serviceActions.add(it)
|
||||||
|
} else {
|
||||||
|
firstActions.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val context = ClassName("android.content", "Context")
|
||||||
|
val packageName = "moe.fuqiuluo.shamrock.xposed.actions"
|
||||||
|
val fileSpec = FileSpec.builder(packageName, "AutoActionLoader").addFunction(FunSpec.builder("runFirstActions")
|
||||||
|
.addParameter("ctx", context)
|
||||||
|
.apply {
|
||||||
|
firstActions.forEach { handler ->
|
||||||
|
val annotation = handler.getAnnotationsByType(XposedHook::class).first()
|
||||||
|
val process = annotation.process
|
||||||
|
val className = handler.simpleName.asString()
|
||||||
|
if (process == Process.MAIN) {
|
||||||
|
addStatement("if (PlatformUtils.isMainProcess()) ")
|
||||||
|
} else if (process == Process.MSF) {
|
||||||
|
addStatement("if (PlatformUtils.isMsfProcess()) ")
|
||||||
|
}
|
||||||
|
addStatement("$className().invoke(ctx)")
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
).addFunction(FunSpec.builder("runServiceActions")
|
||||||
|
.addParameter("ctx", context).apply {
|
||||||
|
serviceActions.forEach { handler ->
|
||||||
|
val annotation = handler.getAnnotationsByType(XposedHook::class).first()
|
||||||
|
val process = annotation.process
|
||||||
|
val className = handler.simpleName.asString()
|
||||||
|
if (process == Process.MAIN) {
|
||||||
|
addStatement("if (PlatformUtils.isMainProcess()) ")
|
||||||
|
} else if (process == Process.MSF) {
|
||||||
|
addStatement("if (PlatformUtils.isMsfProcess()) ")
|
||||||
|
}
|
||||||
|
addStatement("$className().invoke(ctx)")
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
).apply {
|
||||||
|
firstActions.forEach {
|
||||||
|
addImport(it.packageName.asString(), it.simpleName.asString())
|
||||||
|
}
|
||||||
|
serviceActions.forEach {
|
||||||
|
addImport(it.packageName.asString(), it.simpleName.asString())
|
||||||
|
}
|
||||||
|
addImport("moe.fuqiuluo.shamrock.utils", "PlatformUtils")
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
codeGenerator.createNewFile(
|
||||||
|
dependencies = Dependencies(aggregating = false),
|
||||||
|
packageName = packageName,
|
||||||
|
fileName = "AutoActionLoader"
|
||||||
|
).use { outputStream ->
|
||||||
|
outputStream.writer().use {
|
||||||
|
fileSpec.writeTo(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return unableToProcess.toList()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package moe.fuqiuluo.ksp.providers
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessor
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessorProvider
|
||||||
|
import moe.fuqiuluo.ksp.impl.GrpcProcessor
|
||||||
|
|
||||||
|
@AutoService(SymbolProcessorProvider::class)
|
||||||
|
class GrpcProvider: SymbolProcessorProvider {
|
||||||
|
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
|
||||||
|
return GrpcProcessor(
|
||||||
|
environment.codeGenerator,
|
||||||
|
environment.logger
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package moe.fuqiuluo.ksp.providers
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessor
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessorProvider
|
||||||
|
import moe.fuqiuluo.ksp.impl.ProtobufProcessor
|
||||||
|
|
||||||
|
@AutoService(SymbolProcessorProvider::class)
|
||||||
|
class ProtobufProvider: SymbolProcessorProvider {
|
||||||
|
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
|
||||||
|
return ProtobufProcessor(
|
||||||
|
environment.codeGenerator,
|
||||||
|
environment.logger
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package moe.fuqiuluo.ksp.providers
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessor
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessorProvider
|
||||||
|
import moe.fuqiuluo.ksp.impl.XposedHookProcessor
|
||||||
|
|
||||||
|
@AutoService(SymbolProcessorProvider::class)
|
||||||
|
class XposedHookProcessorProvider: SymbolProcessorProvider {
|
||||||
|
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
|
||||||
|
return XposedHookProcessor(environment.codeGenerator, environment.logger)
|
||||||
|
}
|
||||||
|
}
|
1
protobuf/.gitignore
vendored
Normal file
1
protobuf/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build
|
50
protobuf/build.gradle.kts
Normal file
50
protobuf/build.gradle.kts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("com.android.library")
|
||||||
|
id("org.jetbrains.kotlin.android")
|
||||||
|
kotlin("plugin.serialization") version "1.9.22"
|
||||||
|
id("com.google.devtools.ksp") version "1.9.22-1.0.17"
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "moe.whitechi73.protobuf"
|
||||||
|
compileSdk = 34
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk = 24
|
||||||
|
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
consumerProguardFiles("consumer-rules.pro")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(kotlinx("serialization-protobuf", "1.6.2"))
|
||||||
|
implementation(kotlinx("serialization-json", "1.6.2"))
|
||||||
|
|
||||||
|
implementation(project(":annotations"))
|
||||||
|
|
||||||
|
ksp(project(":processor"))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<KotlinCompile>().configureEach {
|
||||||
|
kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
|
||||||
|
}
|
0
protobuf/consumer-rules.pro
Normal file
0
protobuf/consumer-rules.pro
Normal file
21
protobuf/proguard-rules.pro
vendored
Normal file
21
protobuf/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
4
protobuf/src/main/AndroidManifest.xml
Normal file
4
protobuf/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
</manifest>
|
128
protobuf/src/main/java/protobuf/fav/WeiyunAddRichMediaReq.kt
Normal file
128
protobuf/src/main/java/protobuf/fav/WeiyunAddRichMediaReq.kt
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
@file:Suppress("ArrayInDataClass")
|
||||||
|
|
||||||
|
package protobuf.fav
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunAddRichMediaReq(
|
||||||
|
@ProtoNumber(1) val commInfo: WeiyunCollectCommInfo? = null,
|
||||||
|
@ProtoNumber(2) val summary: WeiyunRichMediaSummary? = null,
|
||||||
|
@ProtoNumber(3) val richMediaContent: List<WeiyunRichMediaContent>? = null,
|
||||||
|
@ProtoNumber(4) val needShareUrl: Boolean = false,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunRichMediaSummary(
|
||||||
|
@ProtoNumber(1) val title: String? = null,
|
||||||
|
@ProtoNumber(2) val subTitle: String = "",
|
||||||
|
@ProtoNumber(3) val brief: String = "",
|
||||||
|
@ProtoNumber(4) val picList: List<WeiyunPicInfo>? = null,
|
||||||
|
@ProtoNumber(5) val contentType: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(6) val originalUri: String = "",
|
||||||
|
@ProtoNumber(7) val publisher: String = "",
|
||||||
|
@ProtoNumber(8) val richMediaVersion: UInt = UInt.MIN_VALUE,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunRichMediaContent(
|
||||||
|
@ProtoNumber(1) val richMedia: WeiyunRichMedia? = null,
|
||||||
|
@ProtoNumber(2) val rawData: ByteArray? = null,
|
||||||
|
@ProtoNumber(3) val bizDataList: List<ByteArray>? = null,
|
||||||
|
@ProtoNumber(4) val picList: List<WeiyunPicInfo>? = null,
|
||||||
|
@ProtoNumber(5) val fileList: List<WeiyunFileInfo>? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunFileInfo(
|
||||||
|
@ProtoNumber(1) val src: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(2) val uid: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(3) val bid: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(4) val fid: String = "",
|
||||||
|
@ProtoNumber(5) val name: String = "",
|
||||||
|
@ProtoNumber(6) val size: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(7) val md5: ByteArray? = null,
|
||||||
|
@ProtoNumber(8) val sha1: ByteArray? = null,
|
||||||
|
@ProtoNumber(9) val category: UInt = UInt.MIN_VALUE,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunRichMedia(
|
||||||
|
@ProtoNumber(1) val sections: List<WeiyunSection>? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunSection(
|
||||||
|
@ProtoNumber(1) val items: List<WeiyunItem>? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunItem(
|
||||||
|
@ProtoNumber(1) val itemType: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(2) val paragraph: WeiyunParagraph? = null,
|
||||||
|
@ProtoNumber(3) val anchor: WeiyunAnchor? = null,
|
||||||
|
@ProtoNumber(4) val picInfo: WeiyunPicInfo? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunPicInfo(
|
||||||
|
@ProtoNumber(1) val uri: String = "",
|
||||||
|
@ProtoNumber(2) val md5: ByteArray? = null,
|
||||||
|
@ProtoNumber(3) val sha1: ByteArray? = null,
|
||||||
|
@ProtoNumber(4) val name: String = "",
|
||||||
|
@ProtoNumber(5) val note: String = "",
|
||||||
|
@ProtoNumber(6) val width: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(7) val height: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(8) val size: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(9) val type: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(10) val owner: WeiyunAuthor? = null,
|
||||||
|
@ProtoNumber(11) val picId: String = "",
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunAnchor(
|
||||||
|
@ProtoNumber(1) val url: String = "",
|
||||||
|
@ProtoNumber(2) val desc: String = "",
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunParagraph(
|
||||||
|
@ProtoNumber(1) val content: String = "",
|
||||||
|
@ProtoNumber(2) val style: WeiyunStyle? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunStyle(
|
||||||
|
@ProtoNumber(1) val color: String = "#FFFFFF",
|
||||||
|
@ProtoNumber(2) val fontFamily: String = "",
|
||||||
|
@ProtoNumber(3) val fontWeight: String = "normal",
|
||||||
|
@ProtoNumber(4) val fontSize: String = "",
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunCollectCommInfo(
|
||||||
|
@ProtoNumber(1) val bid: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(2) val category: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(3) val author: WeiyunAuthor? = null,
|
||||||
|
@ProtoNumber(4) val createTime: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(5) val seq: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(6) val bizKey: String = "",
|
||||||
|
@ProtoNumber(7) val bizDataList: List<ByteArray>? = null,
|
||||||
|
@ProtoNumber(8) val shareUrl: String = "",
|
||||||
|
@ProtoNumber(9) val originalAppId: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(10) val customGroupId: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(11) val modifyTime: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(12) val qzoneUgcKey: String = "",
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunAuthor(
|
||||||
|
@ProtoNumber(1) val type: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(2) val numId: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(3) val strId: String = "",
|
||||||
|
@ProtoNumber(4) val groupId: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(5) val groupName: String = "",
|
||||||
|
)
|
@ -0,0 +1,13 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
package protobuf.fav
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunAddRichMediaResp(
|
||||||
|
@ProtoNumber(1) val cid: String = "",
|
||||||
|
@ProtoNumber(2) val collectTime: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(3) val shareUrl: String = "",
|
||||||
|
)
|
11
protobuf/src/main/java/protobuf/fav/WeiyunComm.kt
Normal file
11
protobuf/src/main/java/protobuf/fav/WeiyunComm.kt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package protobuf.fav
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
import moe.fuqiuluo.symbols.Protobuf
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunComm(
|
||||||
|
@ProtoNumber(1) val req: WeiyunCommonReq? = null,
|
||||||
|
@ProtoNumber(2) val resp: WeiyunCommonResp? = null
|
||||||
|
): Protobuf<WeiyunComm>
|
15
protobuf/src/main/java/protobuf/fav/WeiyunCommonReq.kt
Normal file
15
protobuf/src/main/java/protobuf/fav/WeiyunCommonReq.kt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
package protobuf.fav
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunCommonReq (
|
||||||
|
@ProtoNumber(2000) val getFavListReq: WeiyunGetFavListReq? = null,
|
||||||
|
@ProtoNumber(2001) val getFavContentReq: WeiyunGetFavContentReq? = null,
|
||||||
|
@ProtoNumber(2009) val addRichMediaReq: WeiyunAddRichMediaReq? = null,
|
||||||
|
@ProtoNumber(2010) val fastUploadResourceReq: WeiyunFastUploadResourceReq? = null,
|
||||||
|
|
||||||
|
)
|
14
protobuf/src/main/java/protobuf/fav/WeiyunCommonResp.kt
Normal file
14
protobuf/src/main/java/protobuf/fav/WeiyunCommonResp.kt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
package protobuf.fav
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunCommonResp(
|
||||||
|
@ProtoNumber(20000) val getFavListResp: WeiyunGetFavListResp? = null,
|
||||||
|
@ProtoNumber(20001) val getFavContentResp: WeiyunGetFavContentResp? = null,
|
||||||
|
@ProtoNumber(20009) val addRichMediaResp: WeiyunAddRichMediaResp? = null,
|
||||||
|
@ProtoNumber(20010) val fastUploadResourceResp: WeiyunFastUploadResourceResp? = null,
|
||||||
|
)
|
@ -0,0 +1,14 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
package protobuf.fav
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunFastUploadResourceReq(
|
||||||
|
@ProtoNumber(1) val picInfoList: List<WeiyunPicInfo>? = null,
|
||||||
|
@ProtoNumber(2) val fileInfoList: List<WeiyunFileInfo>? = null,
|
||||||
|
@ProtoNumber(3) val hostFlag: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(4) val httpsFlag: UInt = UInt.MIN_VALUE,
|
||||||
|
)
|
@ -0,0 +1,39 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
|
||||||
|
package protobuf.fav
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunFastUploadResourceResp(
|
||||||
|
@ProtoNumber(1) val picResultList: List<WeiyunFastUploadPicResult>? = null,
|
||||||
|
@ProtoNumber(2) val fileResultList: List<WeiyunFastUploadFileResult>? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunFastUploadPicResult(
|
||||||
|
@ProtoNumber(1) val result: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(2) val picInfo: WeiyunPicInfo? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunFastUploadFileResult(
|
||||||
|
@ProtoNumber(1) val result: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(2) val picInfo: WeiyunPicInfo? = null,
|
||||||
|
@ProtoNumber(3) val uploadFileInfo: WeiyunUploadFileInfo? = null,
|
||||||
|
@ProtoNumber(4) val notRetransmission: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(5) val failedTips: String = "",
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunUploadFileInfo(
|
||||||
|
@ProtoNumber(1) val fileId: String = "",
|
||||||
|
@ProtoNumber(2) val sha1: ByteArray? = null,
|
||||||
|
@ProtoNumber(3) val checkKey: ByteArray? = null,
|
||||||
|
@ProtoNumber(4) val host: String = "",
|
||||||
|
@ProtoNumber(5) val port: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(6) val httpsHost: String = "",
|
||||||
|
@ProtoNumber(7) val httpsPort: UInt = UInt.MIN_VALUE,
|
||||||
|
)
|
@ -0,0 +1,11 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
package protobuf.fav
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunGetFavContentReq(
|
||||||
|
@ProtoNumber(1) var cidList: List<String> = emptyList(),
|
||||||
|
)
|
@ -0,0 +1,50 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
package protobuf.fav
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunGetFavContentResp(
|
||||||
|
@ProtoNumber(1) val content: List<WeiyunContent>? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunContent(
|
||||||
|
@ProtoNumber(1) val text: WeiyunTextContent? = null,
|
||||||
|
@ProtoNumber(2) val link: WeiyunLinkContent? = null,
|
||||||
|
@ProtoNumber(3) val galley: WeiyunGalleyContent? = null,
|
||||||
|
@ProtoNumber(4) val audio: WeiyunAudioContent? = null,
|
||||||
|
@ProtoNumber(5) val video: WeiyunVideoContent? = null,
|
||||||
|
@ProtoNumber(6) val file: WeiyunFileContent? = null,
|
||||||
|
@ProtoNumber(7) val location: WeiyunLocationContent? = null,
|
||||||
|
@ProtoNumber(8) val richMedia: WeiyunRichMediaContent? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunTextContent(
|
||||||
|
@ProtoNumber(1) val data: String,
|
||||||
|
@ProtoNumber(2) val hasEmoji: Boolean = false
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class WeiyunLinkContent
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class WeiyunGalleyContent
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunAudioContent(
|
||||||
|
@ProtoNumber(1) val data: ByteArray,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class WeiyunVideoContent
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class WeiyunFileContent
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class WeiyunLocationContent
|
||||||
|
|
19
protobuf/src/main/java/protobuf/fav/WeiyunGetFavListReq.kt
Normal file
19
protobuf/src/main/java/protobuf/fav/WeiyunGetFavListReq.kt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
package protobuf.fav
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunGetFavListReq(
|
||||||
|
@ProtoNumber(1) val type: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(2) val bid: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(3) val category: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(4) val startTime: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(5) val orderType: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(6) val startPos: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(7) val pageSize: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(8) val syncPolicy: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(9) val reqSource: UInt = UInt.MIN_VALUE,
|
||||||
|
)
|
41
protobuf/src/main/java/protobuf/fav/WeiyunGetFavListResp.kt
Normal file
41
protobuf/src/main/java/protobuf/fav/WeiyunGetFavListResp.kt
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
|
||||||
|
package protobuf.fav
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunGetFavListResp(
|
||||||
|
@ProtoNumber(1) val collections: List<WeiyunCollection>? = null,
|
||||||
|
@ProtoNumber(2) val totalCnt: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(3) val result: UInt = UInt.MIN_VALUE,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunCollection(
|
||||||
|
@ProtoNumber(1) val cid: String = "",
|
||||||
|
@ProtoNumber(2) val type: Int = Int.MIN_VALUE,
|
||||||
|
@ProtoNumber(3) val status: Int = Int.MIN_VALUE,
|
||||||
|
@ProtoNumber(4) val author: WeiyunAuthor? = null,
|
||||||
|
@ProtoNumber(5) val bid: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(6) val srcAppId: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(7) val srcAppVer: String = "",
|
||||||
|
@ProtoNumber(8) val category: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(9) val createTime: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(10) val collectTime: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(11) val modifyTime: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(12) val seq: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(13) val bizKey: String = "",
|
||||||
|
@ProtoNumber(14) val bizDataList: List<ByteArray>? = null,
|
||||||
|
@ProtoNumber(15) val summary: String = "",
|
||||||
|
@ProtoNumber(16) val starMark: Boolean = false,
|
||||||
|
@ProtoNumber(17) val starTime: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(18) val shareUrl: String = "",
|
||||||
|
@ProtoNumber(19) val originalAppId: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(20) val customGroupId: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(21) val securityBeat: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(22) val qzoneUgcKey: String = "",
|
||||||
|
)
|
||||||
|
|
32
protobuf/src/main/java/protobuf/fav/WeiyunMsgHead.kt
Normal file
32
protobuf/src/main/java/protobuf/fav/WeiyunMsgHead.kt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
@file:Suppress("ArrayInDataClass")
|
||||||
|
|
||||||
|
package protobuf.fav
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
import moe.fuqiuluo.symbols.Protobuf
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class WeiyunMsgHead(
|
||||||
|
@ProtoNumber(1) val uin: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(2) val seq: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(3) val type: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(4) val cmd: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(5) val appId: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(6) val version: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(7) val netType: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(8) val clientIp: String? = null,
|
||||||
|
@ProtoNumber(9) val encrypt: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(10) val keyType: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(11) val key: ByteArray? = null,
|
||||||
|
@ProtoNumber(14) val majorVersion: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(15) val minorVersion: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(101) val retCode: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(102) val retMsg: String? = null,
|
||||||
|
@ProtoNumber(103) val promptMsg: String? = null,
|
||||||
|
@ProtoNumber(111) val totalSpace: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(112) val usedSpace: ULong = ULong.MIN_VALUE,
|
||||||
|
): Protobuf<WeiyunMsgHead>
|
||||||
|
|
@ -0,0 +1,20 @@
|
|||||||
|
package protobuf.group_file_common
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class FolderInfo(
|
||||||
|
@SerialName("folder_id") @ProtoNumber(1) val folderId: String = "",
|
||||||
|
@SerialName("parent_folder_id") @ProtoNumber(2) val parentFolderId: String = "",
|
||||||
|
@SerialName("folder_name") @ProtoNumber(3) val folderName: String = "",
|
||||||
|
@SerialName("create_time") @ProtoNumber(4) val createTime: UInt = UInt.MIN_VALUE,
|
||||||
|
@SerialName("modify_time") @ProtoNumber(5) val modifyTime: UInt = UInt.MIN_VALUE,
|
||||||
|
@SerialName("creator_uin") @ProtoNumber(6) val createUin: ULong = ULong.MIN_VALUE,
|
||||||
|
@SerialName("creator_name") @ProtoNumber(7) val creatorName: String? = null,
|
||||||
|
@SerialName("total_file_cnt") @ProtoNumber(8) val totalFileCnt: UInt = UInt.MIN_VALUE,
|
||||||
|
@SerialName("modifier_uin") @ProtoNumber(9) val modifyUin: ULong? = null,
|
||||||
|
@SerialName("modifier_name") @ProtoNumber(10) val modifierName: String? = null,
|
||||||
|
@SerialName("used_space") @ProtoNumber(11) val usedSpace: ULong = ULong.MIN_VALUE,
|
||||||
|
)
|
406
protobuf/src/main/java/protobuf/guild/GetGuildFeeds.kt
Normal file
406
protobuf/src/main/java/protobuf/guild/GetGuildFeeds.kt
Normal file
@ -0,0 +1,406 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
|
||||||
|
package protobuf.guild
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
import moe.fuqiuluo.symbols.Protobuf
|
||||||
|
import protobuf.qweb.QWebExtInfo
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GetGuildFeedsReq(
|
||||||
|
@ProtoNumber(1) var count: Int,
|
||||||
|
@ProtoNumber(2) var from: Int? = null,
|
||||||
|
@ProtoNumber(3) var feedAttchInfo: ByteArray? = null,
|
||||||
|
@ProtoNumber(4) var guildId: ULong? = null,
|
||||||
|
@ProtoNumber(5) var getType: Int? = null,
|
||||||
|
@ProtoNumber(6) var sortOption: Int? = null,
|
||||||
|
@ProtoNumber(7) var u7: Int? = null,
|
||||||
|
@ProtoNumber(8) var u8: Int? = null,
|
||||||
|
@ProtoNumber(9) var u9: ByteArray? = null,
|
||||||
|
): Protobuf<GetGuildFeedsReq>
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GetGuildFeedsRsp(
|
||||||
|
@ProtoNumber(1) var vecFeed: List<StFeed>? = null,
|
||||||
|
@ProtoNumber(2) var isFinish: Int = 0,
|
||||||
|
//@ProtoNumber(3) var feedAttchInfo: ByteArray? = null,
|
||||||
|
//@ProtoNumber(4) var traceId: String? = null,
|
||||||
|
): Protobuf<GetGuildFeedsRsp>
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StFeed(
|
||||||
|
@SerialName("id") @ProtoNumber(1) var id: String,
|
||||||
|
@SerialName("title") @ProtoNumber(2) var title: StRichText,
|
||||||
|
@SerialName("poster") @ProtoNumber(4) var poster: StUser? = null,
|
||||||
|
@SerialName("videos") @ProtoNumber(5) var videos: List<StVideo>? = null,
|
||||||
|
@SerialName("contents") @ProtoNumber(6) var contents: StRichText? = null,
|
||||||
|
@SerialName("create_time") @ProtoNumber(7) var createTime: ULong? = null,
|
||||||
|
@SerialName("comment_count") @ProtoNumber(9) var commentCount: UInt? = null,
|
||||||
|
|
||||||
|
@SerialName("comments") @ProtoNumber(10) var vecComment: List<StComment>? = null,
|
||||||
|
@SerialName("share") @ProtoNumber(11) var share: StShare? = null,
|
||||||
|
@SerialName("visitor_info") @ProtoNumber(12) var visitorInfo: StVisitor? = null,
|
||||||
|
@SerialName("images") @ProtoNumber(13) var images: List<StImage>? = null,
|
||||||
|
@SerialName("poi") @ProtoNumber(14) var poiInfo: StPoiInfoV2? = null,
|
||||||
|
@SerialName("op_mask") @ProtoNumber(17) var opMask: List<Int>? = null,
|
||||||
|
@SerialName("channel_info") @ProtoNumber(21) var channelInfo: StChannelInfo? = null,
|
||||||
|
@SerialName("create_time_ns") @ProtoNumber(22) var createTimeNs: ULong? = null,
|
||||||
|
@SerialName("update_time") @ProtoNumber(28) var updateTime: ULong? = null,
|
||||||
|
@SerialName("total_like") @ProtoNumber(29) var totalLike: StTotalLike? = null,
|
||||||
|
@SerialName("discussion_mum") @ProtoNumber(31) var discussionMum: UInt? = null,
|
||||||
|
@SerialName("feed_type") @ProtoNumber(32) var feedType: UInt? = null,
|
||||||
|
@SerialName("default_background_img") @ProtoNumber(34) var defaultBackgroundImg: String? = null,
|
||||||
|
@SerialName("group_code") @ProtoNumber(35) var groupCode: ULong? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StTotalLike (
|
||||||
|
@SerialName("count") @ProtoNumber(1) var likeCount: UInt? = null,
|
||||||
|
@SerialName("is_clicked") @ProtoNumber(2) var isClicked: UInt? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StPoiInfoV2(
|
||||||
|
@SerialName("poi_id") @ProtoNumber(1) var poiId: String? = null,
|
||||||
|
@SerialName("name") @ProtoNumber(2) var name: String? = null,
|
||||||
|
@SerialName("poi_type") @ProtoNumber(3) var poiType: Int? = null,
|
||||||
|
@SerialName("type_name") @ProtoNumber(4) var typeName: String? = null,
|
||||||
|
@SerialName("address") @ProtoNumber(5) var address: String? = null,
|
||||||
|
@SerialName("district_code") @ProtoNumber(6) var districtCode: Int? = null,
|
||||||
|
@SerialName("gps") @ProtoNumber(7) var gps: StGPSV2? = null,
|
||||||
|
@SerialName("distance") @ProtoNumber(8) var distance: Int? = null,
|
||||||
|
@SerialName("hot_value") @ProtoNumber(9) var hotValue: Int? = null,
|
||||||
|
@SerialName("phone") @ProtoNumber(10) var phone: String? = null,
|
||||||
|
@SerialName("country") @ProtoNumber(11) var country: String? = null,
|
||||||
|
@SerialName("province") @ProtoNumber(12) var province: String? = null,
|
||||||
|
@SerialName("city") @ProtoNumber(13) var city: String? = null,
|
||||||
|
@SerialName("poi_num") @ProtoNumber(14) var poiNum: Int? = null,
|
||||||
|
@SerialName("poi_order_type") @ProtoNumber(15) var poiOrderType: Int? = null,
|
||||||
|
@SerialName("default_name") @ProtoNumber(16) var defaultName: String? = null,
|
||||||
|
@SerialName("district") @ProtoNumber(17) var district: String? = null,
|
||||||
|
@SerialName("dian_ping_id") @ProtoNumber(18) var dianPingId: String? = null,
|
||||||
|
@SerialName("distance_text") @ProtoNumber(19) var distanceText: String? = null,
|
||||||
|
@SerialName("display_name") @ProtoNumber(20) var displayName: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StGPSV2(
|
||||||
|
@SerialName("lat") @ProtoNumber(1) var latitude: Long? = null,
|
||||||
|
@SerialName("lon") @ProtoNumber(2) var longitude: Long? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StShare(
|
||||||
|
@SerialName("title") @ProtoNumber(1) var title: String? = null,
|
||||||
|
@SerialName("desc") @ProtoNumber(2) var desc: String? = null,
|
||||||
|
@SerialName("type") @ProtoNumber(3) var type: UInt? = null,
|
||||||
|
@SerialName("url") @ProtoNumber(4) var url: String? = null,
|
||||||
|
@SerialName("author") @ProtoNumber(5) var author: StUser? = null,
|
||||||
|
@SerialName("poster") @ProtoNumber(6) var poster: StUser? = null,
|
||||||
|
@SerialName("videos") @ProtoNumber(7) var videos: List<StVideo>? = null,
|
||||||
|
@SerialName("short_url") @ProtoNumber(8) var shorturl: String? = null,
|
||||||
|
@SerialName("share_card_info") @ProtoNumber(9) var shareCardInfo: String? = null,
|
||||||
|
//@ProtoNumber(10) var shareQzoneInfo: Any? = null,
|
||||||
|
@SerialName("images") @ProtoNumber(11) var images: List<StImage>? = null,
|
||||||
|
@SerialName("publish_total_user") @ProtoNumber(12) var publishTotalUser: UInt? = null,
|
||||||
|
@SerialName("shared_count") @ProtoNumber(13) var sharedCount: UInt? = null,
|
||||||
|
//@ProtoNumber(14) var channelShareInfo: Any? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StVisitor(
|
||||||
|
@SerialName("view_count")
|
||||||
|
@ProtoNumber(1) val viewCount: UInt? = null,
|
||||||
|
@SerialName("recome_count")
|
||||||
|
@ProtoNumber(3) val recomeCount: UInt? = null,
|
||||||
|
@SerialName("view_desc")
|
||||||
|
@ProtoNumber(4) val viewDesc: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StComment(
|
||||||
|
@SerialName("id") @ProtoNumber(1) var id: String? = null,
|
||||||
|
@SerialName("poster") @ProtoNumber(2) var postUser: StUser? = null,
|
||||||
|
@SerialName("create_time") @ProtoNumber(3) var createTime: ULong? = null,
|
||||||
|
@SerialName("content") @ProtoNumber(4) var content: String? = null,
|
||||||
|
@SerialName("reply_count") @ProtoNumber(5) var replyCount: UInt? = null,
|
||||||
|
@SerialName("replies") @ProtoNumber(6) var vecReply: List<StReply>? = null,
|
||||||
|
//@ProtoNumber(7) var busiData: Any? = null,
|
||||||
|
@SerialName("like_info") @ProtoNumber(8) var likeInfo: StLike? = null,
|
||||||
|
@SerialName("type_flag") @ProtoNumber(9) var typeFlag: UInt? = null,
|
||||||
|
@SerialName("at_uin_list") @ProtoNumber(10) var atUinList: List<String>? = null,
|
||||||
|
@SerialName("type_flag2") @ProtoNumber(11) var typeFlag2: UInt? = null,
|
||||||
|
@SerialName("create_time_ns") @ProtoNumber(12) var createTimeNs: ULong? = null,
|
||||||
|
@SerialName("store_ext_info") @ProtoNumber(13) var storeExtInfo: List<QWebExtInfo>? = null,
|
||||||
|
@SerialName("third_id") @ProtoNumber(14) var thirdId: String? = null,
|
||||||
|
@SerialName("source_type") @ProtoNumber(15) var sourceType: UInt? = null,
|
||||||
|
@SerialName("rich_contents") @ProtoNumber(16) var richContents: StRichText? = null,
|
||||||
|
@SerialName("images") @ProtoNumber(17) var images: List<StImage>? = null,
|
||||||
|
@SerialName("sequence") @ProtoNumber(18) var sequence: ULong? = null,
|
||||||
|
@SerialName("next_page_reply") @ProtoNumber(19) var nextPageReply: Boolean? = null,
|
||||||
|
@SerialName("attach_info") @ProtoNumber(20) var attachInfo: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StReply(
|
||||||
|
@SerialName("id") @ProtoNumber(1) var id: String? = null,
|
||||||
|
@SerialName("poster") @ProtoNumber(2) var postUser: StUser? = null,
|
||||||
|
@SerialName("create_time") @ProtoNumber(3) var createTime: ULong? = null,
|
||||||
|
@SerialName("content") @ProtoNumber(4) var content: String? = null,
|
||||||
|
@SerialName("target") @ProtoNumber(5) var targetUser: StUser? = null,
|
||||||
|
//@ProtoNumber(6) var busiData: ByteArray? = null,
|
||||||
|
@SerialName("like_info") @ProtoNumber(7) var likeInfo: StLike? = null,
|
||||||
|
@SerialName("type_flag") @ProtoNumber(8) var typeFlag: UInt? = null,
|
||||||
|
@SerialName("modify_flag") @ProtoNumber(9) var modifyflag: UInt? = null,
|
||||||
|
@SerialName("at_uin_list") @ProtoNumber(10) var atUinList: List<String>? = null,
|
||||||
|
@SerialName("type_flag2") @ProtoNumber(11) var typeFlag2: UInt? = null,
|
||||||
|
@SerialName("create_time_ns") @ProtoNumber(12) var createTimeNs: ULong? = null,
|
||||||
|
@SerialName("store_ext_info") @ProtoNumber(13) var storeExtInfo: List<QWebExtInfo>? = null,
|
||||||
|
@SerialName("third_id") @ProtoNumber(14) var thirdId: String? = null,
|
||||||
|
@SerialName("target_reply_id") @ProtoNumber(15) var targetReplyID: String? = null,
|
||||||
|
@SerialName("source_type") @ProtoNumber(16) var sourceType: UInt? = null,
|
||||||
|
@SerialName("rich_contents") @ProtoNumber(17) var richContents: StRichText? = null,
|
||||||
|
@SerialName("images") @ProtoNumber(18) var images: List<StImage>? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StLike(
|
||||||
|
@SerialName("id")
|
||||||
|
@ProtoNumber(1) var id: String? = null,
|
||||||
|
@SerialName("count")
|
||||||
|
@ProtoNumber(2) var count: UInt? = null,
|
||||||
|
@SerialName("status")
|
||||||
|
@ProtoNumber(3) var status: UInt? = null,
|
||||||
|
@SerialName("like_uin_list")
|
||||||
|
@ProtoNumber(4) var vecUser: List<StUser>? = null,
|
||||||
|
@SerialName("poster")
|
||||||
|
@ProtoNumber(6) var postUser: StUser? = null,
|
||||||
|
@SerialName("has_liked_count")
|
||||||
|
@ProtoNumber(7) var hasLikedCount: UInt? = null,
|
||||||
|
@SerialName("owner_status")
|
||||||
|
@ProtoNumber(8) var ownerStatus: UInt? = null,
|
||||||
|
@SerialName("jump_url")
|
||||||
|
@ProtoNumber(9) var jumpUrl: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StVideo(
|
||||||
|
@SerialName("file_id") @ProtoNumber(1) var fileId: String? = null,
|
||||||
|
@SerialName("file_size") @ProtoNumber(2) var fileSize: UInt? = null,
|
||||||
|
@SerialName("duration") @ProtoNumber(3) var duration: UInt? = null,
|
||||||
|
@SerialName("width") @ProtoNumber(4) var width: UInt? = null,
|
||||||
|
@SerialName("height") @ProtoNumber(5) var height: UInt? = null,
|
||||||
|
@SerialName("play_url") @ProtoNumber(6) var playUrl: String? = null,
|
||||||
|
@SerialName("trans_status") @ProtoNumber(7) var transStatus: UInt? = null,
|
||||||
|
@SerialName("video_prior") @ProtoNumber(8) var videoPrior: UInt? = null,
|
||||||
|
@SerialName("video_rate") @ProtoNumber(9) var videoRate: UInt? = null,
|
||||||
|
//@ProtoNumber(10) var vecVideoUrl: String? = null,
|
||||||
|
//@ProtoNumber(11) var busiData: Any? = null,
|
||||||
|
@SerialName("approval_status") @ProtoNumber(12) var approvalStatus: UInt? = null,
|
||||||
|
@SerialName("video_source") @ProtoNumber(13) var videoSource: UInt? = null,
|
||||||
|
@SerialName("media_quality_rank") @ProtoNumber(14) var mediaQualityRank: UInt? = null,
|
||||||
|
@SerialName("media_quality_score") @ProtoNumber(15) var mediaQualityScore: Float? = null,
|
||||||
|
@SerialName("md5") @ProtoNumber(16) var videoMD5: String? = null,
|
||||||
|
@SerialName("is_quic") @ProtoNumber(17) var isQuic: UInt? = null,
|
||||||
|
@SerialName("orientation") @ProtoNumber(18) var orientation: Int? = null,
|
||||||
|
@SerialName("cover") @ProtoNumber(19) var cover: StImage? = null,
|
||||||
|
@SerialName("pattern_id") @ProtoNumber(20) var patternId: String? = null,
|
||||||
|
@SerialName("display_index") @ProtoNumber(21) var displayIndex: UInt? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StRichText(
|
||||||
|
@SerialName("contents") @ProtoNumber(1) var contents: List<StRichTextContent>? = null,
|
||||||
|
@SerialName("images") @ProtoNumber(2) var images: List<StImage>? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StRichTextContent(
|
||||||
|
@SerialName("type") @ProtoNumber(1) var type: Int? = null,
|
||||||
|
@SerialName("pattern_id") @ProtoNumber(2) var patternId: String? = null,
|
||||||
|
@SerialName("text") @ProtoNumber(3) var textContent: StRichTextTextContent? = null,
|
||||||
|
@SerialName("at") @ProtoNumber(4) var atContent: StRichTextAtContent? = null,
|
||||||
|
@SerialName("url") @ProtoNumber(5) var urlContent: StRichTextURLContent? = null,
|
||||||
|
@SerialName("emoji") @ProtoNumber(6) var emojiContent: StRichTextEmojiContent? = null,
|
||||||
|
@SerialName("channel") @ProtoNumber(7) var channelContent: StRichTextChannelContent? = null,
|
||||||
|
@SerialName("guild") @ProtoNumber(8) var guildContent: StRichTextGuildContent? = null,
|
||||||
|
@SerialName("icon") @ProtoNumber(9) var iconContent: StRichTextIconContent? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StRichTextIconContent(
|
||||||
|
@SerialName("url") @ProtoNumber(1) val url: String? = null
|
||||||
|
)
|
||||||
|
@Serializable
|
||||||
|
data class StRichTextGuildContent(
|
||||||
|
@SerialName("channel_info") @ProtoNumber(1) val channelInfo: StChannelInfo? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StRichTextChannelContent(
|
||||||
|
@SerialName("channel_info") @ProtoNumber(1) val channelInfo: StChannelInfo? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StChannelInfo(
|
||||||
|
//@SerialName("sign") @ProtoNumber(1) var sign: String? = null,
|
||||||
|
@SerialName("name")
|
||||||
|
@ProtoNumber(2) var name: String? = null,
|
||||||
|
@SerialName("icon_url")
|
||||||
|
@ProtoNumber(3) var iconUrl: String? = null,
|
||||||
|
@SerialName("type")
|
||||||
|
@ProtoNumber(4) var privateType: Int? = null,
|
||||||
|
@SerialName("guild_name")
|
||||||
|
@ProtoNumber(5) var guildName: String? = null,
|
||||||
|
@SerialName("hot_icon")
|
||||||
|
@ProtoNumber(6) var hotIcon: String? = null,
|
||||||
|
@SerialName("hot_index")
|
||||||
|
@ProtoNumber(7) var hotIndex: UInt? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StRichTextEmojiContent(
|
||||||
|
@ProtoNumber(1) var id: String? = null,
|
||||||
|
@ProtoNumber(2) var type: String? = null,
|
||||||
|
@ProtoNumber(3) var name: String? = null,
|
||||||
|
@ProtoNumber(4) var url: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StRichTextURLContent(
|
||||||
|
@ProtoNumber(1) var url: String? = null,
|
||||||
|
@SerialName("display") @ProtoNumber(2) var displayText: String? = null,
|
||||||
|
@ProtoNumber(3) var type: Int? = null,
|
||||||
|
@SerialName("play_url") @ProtoNumber(4) var playUrl: String? = null,
|
||||||
|
@SerialName("platform") @ProtoNumber(5) var thirdPlatform: ThirdPlatform? = null,
|
||||||
|
@SerialName("third_video_info") @ProtoNumber(6) var thirdVideoInfo: CommThirdVideoInfo? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class CommThirdVideoInfo(
|
||||||
|
@SerialName("cover") @ProtoNumber(1) val cover: String? = null,
|
||||||
|
@SerialName("duration") @ProtoNumber(2) val duration: ULong? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ThirdPlatform(
|
||||||
|
@ProtoNumber(1) var icon: String? = null,
|
||||||
|
@ProtoNumber(2) var name: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StRichTextTextContent(
|
||||||
|
@ProtoNumber(1) var text: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StRichTextAtContent(
|
||||||
|
@ProtoNumber(1) var type: Int? = null,
|
||||||
|
@SerialName("guild_info") @ProtoNumber(2) var guildInfo: GuildInfo? = null,
|
||||||
|
@SerialName("role_info") @ProtoNumber(3) var roleGroupId: RoleGroupInfo? = null,
|
||||||
|
@ProtoNumber(4) var user: StUser? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StUser(
|
||||||
|
@ProtoNumber(1) var id: String? = null,
|
||||||
|
@ProtoNumber(2) var nick: String? = null,
|
||||||
|
@ProtoNumber(3) var icon: StIconInfo? = null,
|
||||||
|
@ProtoNumber(4) var desc: String? = null,
|
||||||
|
@SerialName("follow_state") @ProtoNumber(5) var followState: UInt? = null,
|
||||||
|
@ProtoNumber(6) var type: UInt? = null,
|
||||||
|
@ProtoNumber(7) var sex: UInt? = null,
|
||||||
|
@ProtoNumber(8) var birthday: ULong? = null,
|
||||||
|
@ProtoNumber(9) var school: String? = null,
|
||||||
|
@ProtoNumber(11) var location: String? = null,
|
||||||
|
//@ProtoNumber(12) var busiData: ByteArray? = null,
|
||||||
|
@SerialName("frd") @ProtoNumber(13) var frdState: UInt? = null,
|
||||||
|
@SerialName("relation_state") @ProtoNumber(14) var relationState: UInt? = null,
|
||||||
|
@SerialName("black_state") @ProtoNumber(15) var blackState: UInt? = null,
|
||||||
|
@ProtoNumber(16) var medal: StTagMedalInfo? = null,
|
||||||
|
@ProtoNumber(17) var constellation: Int? = null,
|
||||||
|
@SerialName("jump_url") @ProtoNumber(18) var jumpUrl: String? = null,
|
||||||
|
@SerialName("location_code") @ProtoNumber(19) var locationCode: String? = null,
|
||||||
|
@SerialName("third_id") @ProtoNumber(20) var thirdId: String? = null,
|
||||||
|
@ProtoNumber(21) var company: String? = null,
|
||||||
|
@SerialName("certification_desc") @ProtoNumber(22) var certificationDesc: String? = null,
|
||||||
|
@SerialName("desc_type") @ProtoNumber(23) var descType: UInt? = null,
|
||||||
|
//@ProtoNumber(24) var channelUserInfo: Any? = null,
|
||||||
|
//@SerialName("login_id") @ProtoNumber(25) var loginId: String? = null,
|
||||||
|
@ProtoNumber(26) var uin: ULong? = null,
|
||||||
|
@SerialName("nick_flag") @ProtoNumber(27) var nickFlag: UInt? = null,
|
||||||
|
@SerialName("manage_tag") @ProtoNumber(28) var manageTag: CustomManageTag? = null,
|
||||||
|
//@SerialName("personal_medal") @ProtoNumber(29) var personalMedal: PersonalMedal? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class PersonalMedal(
|
||||||
|
@SerialName("start") @ProtoNumber(1) val startTime: ULong? = null,
|
||||||
|
@SerialName("end") @ProtoNumber(2) val endTime: ULong? = null,
|
||||||
|
@ProtoNumber(3) var url: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StTagMedalInfo(
|
||||||
|
@SerialName("id") @ProtoNumber(1) val tagId: ULong? = null,
|
||||||
|
@SerialName("name") @ProtoNumber(2) val tagName: String? = null,
|
||||||
|
@ProtoNumber(3) val rank: ULong? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class CustomManageTag(
|
||||||
|
@ProtoNumber(3) val color: UInt? = null,
|
||||||
|
@SerialName("name") @ProtoNumber(2) val tagName: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StIconInfo(
|
||||||
|
//@SerialName("url_40") @ProtoNumber(1) var iconUrl40: String? = null,
|
||||||
|
//@SerialName("url_100") @ProtoNumber(2) var iconUrl100: String? = null,
|
||||||
|
//@SerialName("url_140") @ProtoNumber(3) var iconUrl140: String? = null,
|
||||||
|
//@SerialName("url_640") @ProtoNumber(4) var iconUrl640: String? = null,
|
||||||
|
@SerialName("url") @ProtoNumber(5) var iconUrl: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class RoleGroupInfo(
|
||||||
|
@SerialName("role") @ProtoNumber(1) var roleId: ULong? = null,
|
||||||
|
@ProtoNumber(2) var name: String? = null,
|
||||||
|
@ProtoNumber(3) var color: ULong? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GuildInfo(
|
||||||
|
@SerialName("guild_id") @ProtoNumber(1) var guildId: ULong? = null,
|
||||||
|
@ProtoNumber(2) var name: String? = null,
|
||||||
|
@SerialName("join_time") @ProtoNumber(3) var joinTime: ULong? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StImage(
|
||||||
|
@ProtoNumber(1) var width: UInt? = null,
|
||||||
|
@ProtoNumber(2) var height: UInt? = null,
|
||||||
|
@ProtoNumber(3) var picUrl: String? = null,
|
||||||
|
@SerialName("image_urls") @ProtoNumber(4) var vecImageUrl: List<StImageUrl>? = null,
|
||||||
|
@SerialName("id") @ProtoNumber(5) var picId: String? = null,
|
||||||
|
//@ProtoNumber(6) var busiData: Any? = null,
|
||||||
|
@SerialName("md5") @ProtoNumber(7) var imageMD5: String? = null,
|
||||||
|
@SerialName("layer_pic_url") @ProtoNumber(8) var layerPicUrl: String? = null,
|
||||||
|
@SerialName("pattern_id") @ProtoNumber(9) var patternId: String? = null,
|
||||||
|
@SerialName("display_index") @ProtoNumber(10) var displayIndex: Int? = null,
|
||||||
|
@SerialName("size") @ProtoNumber(11) var origSize: UInt? = null,
|
||||||
|
@SerialName("is_original") @ProtoNumber(12) var isOrig: Boolean? = null,
|
||||||
|
@SerialName("is_gif") @ProtoNumber(13) var isGif: Boolean? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StImageUrl(
|
||||||
|
@SerialName("level_type") @ProtoNumber(1) var levelType: UInt? = null,
|
||||||
|
@ProtoNumber(2) var url: String? = null,
|
||||||
|
@ProtoNumber(3) var width: UInt? = null,
|
||||||
|
@ProtoNumber(4) var height: UInt? = null,
|
||||||
|
//@ProtoNumber(5) var busiData: Any? = null,
|
||||||
|
)
|
42
protobuf/src/main/java/protobuf/lightapp/AdaptShareInfo.kt
Normal file
42
protobuf/src/main/java/protobuf/lightapp/AdaptShareInfo.kt
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
package protobuf.lightapp
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
import moe.fuqiuluo.symbols.Protobuf
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class AdaptShareInfoReq(
|
||||||
|
//@ProtoNumber(1) var extInfo: Any? = null,
|
||||||
|
@ProtoNumber(2) var appid: String? = null,
|
||||||
|
@ProtoNumber(3) var title: String? = null,
|
||||||
|
@ProtoNumber(4) var desc: String? = null,
|
||||||
|
@ProtoNumber(5) var time: ULong? = null,
|
||||||
|
@ProtoNumber(6) var scene: UInt? = null,
|
||||||
|
@ProtoNumber(7) var templetType: UInt? = null,
|
||||||
|
@ProtoNumber(8) var businessType: UInt? = null,
|
||||||
|
@ProtoNumber(9) var picUrl: String? = null,
|
||||||
|
@ProtoNumber(10) var vidUrl: String? = null,
|
||||||
|
@ProtoNumber(11) var jumpUrl: String? = null,
|
||||||
|
@ProtoNumber(12) var iconUrl: String? = null,
|
||||||
|
@ProtoNumber(13) var verType: UInt? = null,
|
||||||
|
@ProtoNumber(14) var shareType: UInt? = null,
|
||||||
|
@ProtoNumber(15) var versionId: String? = null,
|
||||||
|
@ProtoNumber(16) var withShareTicket: UInt? = null,
|
||||||
|
@ProtoNumber(17) var webURL: String? = null,
|
||||||
|
//@ProtoNumber(18) var appidRich: Any? = null,
|
||||||
|
@ProtoNumber(19) var template: Template? = null,
|
||||||
|
//@ProtoNumber(20) var rcvOpenId: Any? = null,
|
||||||
|
): Protobuf<AdaptShareInfoReq>
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Template(
|
||||||
|
@ProtoNumber(1) var templateId: ULong? = null,
|
||||||
|
@ProtoNumber(2) var templateData: ByteArray? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class AdaptShareInfoResp(
|
||||||
|
@ProtoNumber(2) var json: String? = null,
|
||||||
|
): Protobuf<AdaptShareInfoResp>
|
26
protobuf/src/main/java/protobuf/message/AppShareInfo.kt
Normal file
26
protobuf/src/main/java/protobuf/message/AppShareInfo.kt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class AppShareInfo(
|
||||||
|
@ProtoNumber(1) var appshareId: UInt? = null,
|
||||||
|
@ProtoNumber(2) var appshareCookie: ByteArray? = null,
|
||||||
|
@ProtoNumber(3) var appshareResource: PluginInfo? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class PluginInfo(
|
||||||
|
@ProtoNumber(1) var resId: UInt = 0u,
|
||||||
|
@ProtoNumber(2) var pkgName: String = "",
|
||||||
|
@ProtoNumber(3) var newVer: UInt = 0u,
|
||||||
|
@ProtoNumber(4) var resType: UInt = 0u,
|
||||||
|
@ProtoNumber(5) var lanType: UInt = 0u,
|
||||||
|
@ProtoNumber(6) var priority: UInt = 0u,
|
||||||
|
@ProtoNumber(7) var resName: String = "",
|
||||||
|
@ProtoNumber(8) var resDesc: String = "",
|
||||||
|
@ProtoNumber(9) var resUrlBig: String = "",
|
||||||
|
@ProtoNumber(10) var resUrlSmall: String = "",
|
||||||
|
@ProtoNumber(11) var resConf: String = "",
|
||||||
|
)
|
31
protobuf/src/main/java/protobuf/message/ContentHead.kt
Normal file
31
protobuf/src/main/java/protobuf/message/ContentHead.kt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ContentHead(
|
||||||
|
@ProtoNumber(1) val msgType: Int = Int.MIN_VALUE,
|
||||||
|
@ProtoNumber(2) val msgSubType: Int? = null,
|
||||||
|
@ProtoNumber(3) val divSeq: Int? = null,
|
||||||
|
@ProtoNumber(4) val msgViaRandom: Long = Long.MIN_VALUE,
|
||||||
|
@ProtoNumber(5) val sequence: Long? = null,
|
||||||
|
@ProtoNumber(6) val msgTime: Long? = null,
|
||||||
|
@ProtoNumber(7) val u2: Int? = null,
|
||||||
|
@ProtoNumber(8) val u6: Int? = null,
|
||||||
|
@ProtoNumber(9) val u7: Int? = null,
|
||||||
|
@ProtoNumber(11) val msgSeq: Long? = null,
|
||||||
|
@ProtoNumber(12) val msgRandom: Long = Long.MIN_VALUE, // 0x0100000000000000L xor msgViaRandom
|
||||||
|
@ProtoNumber(14) val u4: Long? = null,
|
||||||
|
@ProtoNumber(15) val forwardHead: ForwardHead? = null,
|
||||||
|
@ProtoNumber(28) val u5: Long? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ForwardHead(
|
||||||
|
@ProtoNumber(1) val u1: Int? = null,
|
||||||
|
@ProtoNumber(2) val u2: Int? = null,
|
||||||
|
@ProtoNumber(3) val u3: Int? = null,
|
||||||
|
@ProtoNumber(4) val ub641: String? = null,
|
||||||
|
@ProtoNumber(5) val avatar: String? = null
|
||||||
|
)
|
64
protobuf/src/main/java/protobuf/message/Elem.kt
Normal file
64
protobuf/src/main/java/protobuf/message/Elem.kt
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
import protobuf.message.element.*
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
@Serializable
|
||||||
|
data class Elem(
|
||||||
|
@ProtoNumber(1) val text: TextMsg? = null,
|
||||||
|
@ProtoNumber(2) val face: FaceMsg? = null,
|
||||||
|
// @ProtoNumber(3) val onlineImage: OnlineImage? = null,
|
||||||
|
@ProtoNumber(4) val notOnlineImage: NotOnlineImage? = null,
|
||||||
|
// @ProtoNumber(5) var transElemInfo: TransElem? = null,
|
||||||
|
@ProtoNumber(6) val marketFace: MarketFace? = null,
|
||||||
|
// @ProtoNumber(7) var elemFlags: ElemFlags? = null,
|
||||||
|
@ProtoNumber(8) val customFace: CustomFace? = null,
|
||||||
|
@ProtoNumber(9) var elemFlags2: ElemFlags2? = null,
|
||||||
|
// @ProtoNumber(10) var funFace: FunFace? = null,
|
||||||
|
// @ProtoNumber(11) var secretFile: SecretFileMsg? = null,
|
||||||
|
// @ProtoNumber(12) var richMsg: RichMsg? = null,
|
||||||
|
// @ProtoNumber(13) var groupFile: GroupFile? = null,
|
||||||
|
// @ProtoNumber(14) var pubGroup: PubGroup? = null,
|
||||||
|
// @ProtoNumber(15) var marketTrans: MarketTrans? = null,
|
||||||
|
// @ProtoNumber(16) var extraInfo: ExtraInfo? = null,
|
||||||
|
// @ProtoNumber(17) var shakeWindow: ShakeWindow? = null,
|
||||||
|
// @ProtoNumber(18) var pubAccount: PubAccount? = null,
|
||||||
|
// @ProtoNumber(19) var videoFile: VideoFile? = null,
|
||||||
|
// @ProtoNumber(20) var tipsInfo: TipsInfo? = null,
|
||||||
|
// @ProtoNumber(21) var anonGroupMsg: AnonymousGroupMsg? = null,
|
||||||
|
// @ProtoNumber(22) var qqLiveOld: QQLiveOld? = null,
|
||||||
|
// @ProtoNumber(23) var lifeOnline: LifeOnlineAccount? = null,
|
||||||
|
// @ProtoNumber(24) var qqwalletMsg: QQWalletMsg? = null,
|
||||||
|
// @ProtoNumber(25) var crmElem: CrmElem? = null,
|
||||||
|
// @ProtoNumber(26) var conferenceTipsInfo: ConferenceTipsInfo? = null,
|
||||||
|
// @ProtoNumber(27) var redbagInfo: RedBagInfo? = null,
|
||||||
|
// @ProtoNumber(28) var lowVersionTips: LowVersionTips? = null,
|
||||||
|
// @ProtoNumber(29) var bankcodeCtrlInfo: ByteArray? = null,
|
||||||
|
// @ProtoNumber(30) var nearByMsg: NearByMessageType? = null,
|
||||||
|
// @ProtoNumber(31) var customElem: CustomElem? = null,
|
||||||
|
// @ProtoNumber(32) var locationInfo: LocationInfo? = null,
|
||||||
|
// @ProtoNumber(33) var pubAccInfo: PubAccInfo? = null,
|
||||||
|
// @ProtoNumber(34) var smallEmoji: SmallEmoji? = null,
|
||||||
|
// @ProtoNumber(35) var fsjMsgElem: FSJMessageElem? = null,
|
||||||
|
// @ProtoNumber(36) var arkApp: ArkAppElem? = null,
|
||||||
|
@ProtoNumber(37) val generalFlags: GeneralFlags? = null,
|
||||||
|
// @ProtoNumber(38) var hcFlashPic: CustomFace? = null,
|
||||||
|
// @ProtoNumber(39) var deliverGiftMsg: DeliverGiftMsg? = null,
|
||||||
|
// @ProtoNumber(40) var bitapp_msg: BitAppMsg? = null,
|
||||||
|
// @ProtoNumber(41) var openQqData: OpenQQData? = null,
|
||||||
|
// @ProtoNumber(42) var apolloMsg: ApolloActMsg? = null,
|
||||||
|
// @ProtoNumber(43) var groupPubAccInfo: GroupPubAccountInfo? = null,
|
||||||
|
// @ProtoNumber(44) var blessMsg: BlessingMessage? = null,
|
||||||
|
@ProtoNumber(45) var srcMsg: SourceMsg? = null,
|
||||||
|
// @ProtoNumber(46) var lolaMsg: LolaMsg? = null,
|
||||||
|
// @ProtoNumber(47) var groupBusinessMsg: GroupBusinessMsg? = null,
|
||||||
|
// @ProtoNumber(48) var msgWorkflowNotify: WorkflowNotifyMsg? = null,
|
||||||
|
// @ProtoNumber(49) var patElem: PatsElem? = null,
|
||||||
|
// @ProtoNumber(50) var groupPostElem: GroupPostElem? = null,
|
||||||
|
@ProtoNumber(51) val lightApp: LightAppElem? = null,
|
||||||
|
// @ProtoNumber(52) var eimInfo: EIMInfo? = null,
|
||||||
|
@ProtoNumber(53) val commonElem: CommonElem? = null,
|
||||||
|
)
|
11
protobuf/src/main/java/protobuf/message/MsgBody.kt
Normal file
11
protobuf/src/main/java/protobuf/message/MsgBody.kt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MsgBody(
|
||||||
|
@ProtoNumber(1) val richText: RichText? = null,
|
||||||
|
@ProtoNumber(2) val msgContent: ByteArray? = null,
|
||||||
|
@ProtoNumber(3) val msgEncryptContent: ByteArray? = null
|
||||||
|
)
|
9
protobuf/src/main/java/protobuf/message/MsgControl.kt
Normal file
9
protobuf/src/main/java/protobuf/message/MsgControl.kt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MsgControl(
|
||||||
|
@ProtoNumber(1) val msgFlag: Int? = null,
|
||||||
|
)
|
28
protobuf/src/main/java/protobuf/message/NotOnlineFile.kt
Normal file
28
protobuf/src/main/java/protobuf/message/NotOnlineFile.kt
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class NotOnlineFile(
|
||||||
|
@ProtoNumber(1) var fileType: UInt? = null,
|
||||||
|
@ProtoNumber(2) var sig: ByteArray? = null,
|
||||||
|
@ProtoNumber(3) var fileUuid: ByteArray? = null,
|
||||||
|
@ProtoNumber(4) var fileMd5: ByteArray? = null,
|
||||||
|
@ProtoNumber(5) var fileName: ByteArray? = null,
|
||||||
|
@ProtoNumber(6) var fileSize: ULong? = null,
|
||||||
|
@ProtoNumber(7) var note: ByteArray? = null,
|
||||||
|
@ProtoNumber(8) var reserved: UInt? = null,
|
||||||
|
@ProtoNumber(9) var subcmd: UInt? = null,
|
||||||
|
@ProtoNumber(10) var microCloud: UInt? = null,
|
||||||
|
@ProtoNumber(11) var rptFileUrls: List<String>? = null,
|
||||||
|
@ProtoNumber(12) var downloadFlag: UInt? = null,
|
||||||
|
@ProtoNumber(50) var dangerEvel: UInt? = null,
|
||||||
|
@ProtoNumber(51) var lifeTime: UInt? = null,
|
||||||
|
@ProtoNumber(52) var uploadTime: UInt? = null,
|
||||||
|
@ProtoNumber(53) var absFileType: UInt? = null,
|
||||||
|
@ProtoNumber(54) var clientType: UInt? = null,
|
||||||
|
@ProtoNumber(55) var expireTime: UInt? = null,
|
||||||
|
@ProtoNumber(56) var pbReserve: ByteArray? = null,
|
||||||
|
@ProtoNumber(57) var fileidcrcMedia: String? = null,
|
||||||
|
)
|
23
protobuf/src/main/java/protobuf/message/PbSendMsgReq.kt
Normal file
23
protobuf/src/main/java/protobuf/message/PbSendMsgReq.kt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
import moe.fuqiuluo.symbols.Protobuf
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class PbSendMsgReq(
|
||||||
|
@ProtoNumber(1) val routingHead: RoutingHead? = null,
|
||||||
|
@ProtoNumber(2) val contentHead: ContentHead? = null,
|
||||||
|
@ProtoNumber(3) val msgBody: MsgBody? = null,
|
||||||
|
@ProtoNumber(4) val msgSeq: UInt? = null,
|
||||||
|
@ProtoNumber(5) val msgRand: UInt? = null,
|
||||||
|
@ProtoNumber(6) val syncCookie: ByteArray? = null,
|
||||||
|
@ProtoNumber(7) val appShare: AppShareInfo? = null,
|
||||||
|
@ProtoNumber(8) val msgVia: UInt? = null,
|
||||||
|
@ProtoNumber(9) val dataStatist: UInt? = null,
|
||||||
|
// @ProtoNumber(10) val multiMsgAssist: MultiMsgAssist? = null,
|
||||||
|
// @ProtoNumber(11) val inputNotifyInfo: InputNotifyInfo? = null,
|
||||||
|
@ProtoNumber(12) val ctrl: MsgControl? = null,
|
||||||
|
// @ProtoNumber(13) val receiptReq: ReceiptReq? = null,
|
||||||
|
@ProtoNumber(14) val multiSendSeq: UInt? = null
|
||||||
|
) : Protobuf<PbSendMsgReq>
|
40
protobuf/src/main/java/protobuf/message/Ptt.kt
Normal file
40
protobuf/src/main/java/protobuf/message/Ptt.kt
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Ptt(
|
||||||
|
@ProtoNumber(1) var fileType: UInt?=null,
|
||||||
|
@ProtoNumber(2) var srcUin: ULong?=null,
|
||||||
|
@ProtoNumber(3) var fileUuid: String?=null,
|
||||||
|
@ProtoNumber(4) var fileMd5: ByteArray?=null,
|
||||||
|
@ProtoNumber(5) var fileName: String?=null,
|
||||||
|
@ProtoNumber(6) var fileSize: UInt?=null,
|
||||||
|
@ProtoNumber(7) var reserve: ByteArray?=null,
|
||||||
|
@ProtoNumber(8) var fileId: UInt?=null,
|
||||||
|
@ProtoNumber(9) var serverIp: UInt?=null,
|
||||||
|
@ProtoNumber(10) var serverPort: UInt?=null,
|
||||||
|
@ProtoNumber(11) var boolValid: Boolean = false,
|
||||||
|
@ProtoNumber(12) var signature: ByteArray?=null,
|
||||||
|
@ProtoNumber(13) var shortcut: ByteArray?=null,
|
||||||
|
@ProtoNumber(14) var fileKey: ByteArray?=null,
|
||||||
|
@ProtoNumber(15) var magicPttIndex: UInt?=null,
|
||||||
|
@ProtoNumber(16) var voiceSwitch: UInt?=null,
|
||||||
|
@ProtoNumber(17) var pttUrl: ByteArray?=null,
|
||||||
|
@ProtoNumber(18) var groupFileKey: String?=null,
|
||||||
|
@ProtoNumber(19) var time: UInt?=null,
|
||||||
|
@ProtoNumber(20) var downPara: ByteArray?=null,
|
||||||
|
@ProtoNumber(29) var format: UInt?=null,
|
||||||
|
@ProtoNumber(30) var pbReserve: PbReserve?=null,
|
||||||
|
@ProtoNumber(31) var rptPttUrls: List<String>? = null,
|
||||||
|
@ProtoNumber(32) var downloadFlag: UInt?=null,
|
||||||
|
){
|
||||||
|
companion object{
|
||||||
|
@Serializable
|
||||||
|
data class PbReserve(
|
||||||
|
@ProtoNumber(2) var magic: Int?=null,
|
||||||
|
@ProtoNumber(7) var reserve: Int?=null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
11
protobuf/src/main/java/protobuf/message/PushMsgBody.kt
Normal file
11
protobuf/src/main/java/protobuf/message/PushMsgBody.kt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class PushMsgBody(
|
||||||
|
@ProtoNumber(1) val msgHead: ResponseHead? = null,
|
||||||
|
@ProtoNumber(2) val contentHead: ContentHead? = null,
|
||||||
|
@ProtoNumber(3) val body: MsgBody? = null,
|
||||||
|
)
|
33
protobuf/src/main/java/protobuf/message/ResponseHead.kt
Normal file
33
protobuf/src/main/java/protobuf/message/ResponseHead.kt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ResponseHead(
|
||||||
|
@ProtoNumber(1) val peer: Long = Long.MIN_VALUE,
|
||||||
|
@ProtoNumber(2) val peerUid: String? = null,
|
||||||
|
@ProtoNumber(3) val flag: Int = Int.MIN_VALUE,
|
||||||
|
@ProtoNumber(4) val appId: Int = Int.MIN_VALUE,
|
||||||
|
@ProtoNumber(5) val receiver: Long? = null,
|
||||||
|
@ProtoNumber(6) val receiverUid: String? = null,
|
||||||
|
@ProtoNumber(7) val forward: ResponseForward? = null,
|
||||||
|
@ProtoNumber(8) val responseGrp: ResponseGrp? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ResponseForward(
|
||||||
|
@ProtoNumber(6) val friendName: String? = null,
|
||||||
|
@ProtoNumber(11) val u1: Int? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ResponseGrp(
|
||||||
|
@ProtoNumber(1) val groupCode: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(4) val memberCard: String? = null,
|
||||||
|
@ProtoNumber(5) val u1: Int? = null,
|
||||||
|
@ProtoNumber(7) val groupName: String? = null,
|
||||||
|
@ProtoNumber(10) val u2: Int? = null,
|
||||||
|
)
|
31
protobuf/src/main/java/protobuf/message/RichText.kt
Normal file
31
protobuf/src/main/java/protobuf/message/RichText.kt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
|
||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class RichText(
|
||||||
|
@ProtoNumber(1) val attr: Attr? = null,
|
||||||
|
@ProtoNumber(2) var elements: List<Elem>? = null,
|
||||||
|
@ProtoNumber(3) var not_online_file: NotOnlineFile? = null,
|
||||||
|
@ProtoNumber(4) var ptt: Ptt? = null,
|
||||||
|
@ProtoNumber(5) val tmp_ptt: TmpPtt? = null,
|
||||||
|
@ProtoNumber(6) val trans_211_tmp_msg: Trans211TmpMsg? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Attr(
|
||||||
|
@ProtoNumber(1) val codePage: Int? = null,
|
||||||
|
@ProtoNumber(2) val time: UInt? = null,
|
||||||
|
@ProtoNumber(3) val random: UInt? = null,
|
||||||
|
@ProtoNumber(4) val color: UInt? = null,
|
||||||
|
@ProtoNumber(5) val size: UInt? = null,
|
||||||
|
@ProtoNumber(6) val effect: UInt? = null,
|
||||||
|
@ProtoNumber(7) val charSet: UInt? = null,
|
||||||
|
@ProtoNumber(8) val pitchAndFamily: UInt? = null,
|
||||||
|
@ProtoNumber(9) val fontName: String? = null,
|
||||||
|
@ProtoNumber(10) val reserve_data: ByteArray? = null,
|
||||||
|
)
|
14
protobuf/src/main/java/protobuf/message/RoutingHead.kt
Normal file
14
protobuf/src/main/java/protobuf/message/RoutingHead.kt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
import protobuf.message.routing.*
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class RoutingHead(
|
||||||
|
@ProtoNumber(1) val c2c: C2C? = null,
|
||||||
|
@ProtoNumber(2) val grp: Grp? = null,
|
||||||
|
@ProtoNumber(3) val grpTmp: GrpTmp? = null,
|
||||||
|
@ProtoNumber(6) val wpaTmp: WPATmp? = null,
|
||||||
|
@ProtoNumber(15) val trans0X211: Trans0X211? = null
|
||||||
|
)
|
20
protobuf/src/main/java/protobuf/message/TmpPtt.kt
Normal file
20
protobuf/src/main/java/protobuf/message/TmpPtt.kt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TmpPtt(
|
||||||
|
@ProtoNumber(1) var fileType: UInt? = null,
|
||||||
|
@ProtoNumber(2) var fileUuid: ByteArray? = null,
|
||||||
|
@ProtoNumber(3) var fileMd5: ByteArray? = null,
|
||||||
|
@ProtoNumber(4) var fileName: ByteArray? = null,
|
||||||
|
@ProtoNumber(5) var fileSize: UInt? = null,
|
||||||
|
@ProtoNumber(6) var pttTimes: UInt? = null,
|
||||||
|
@ProtoNumber(7) var userType: UInt? = null,
|
||||||
|
@ProtoNumber(8) var ptttransFlag: UInt? = null,
|
||||||
|
@ProtoNumber(9) var busiType: UInt? = null,
|
||||||
|
@ProtoNumber(10) var msgId: ULong? = null,
|
||||||
|
@ProtoNumber(30) var pbReserve: ByteArray? = null,
|
||||||
|
@ProtoNumber(31) var pttEncodeData: ByteArray? = null,
|
||||||
|
)
|
10
protobuf/src/main/java/protobuf/message/Trans211TmpMsg.kt
Normal file
10
protobuf/src/main/java/protobuf/message/Trans211TmpMsg.kt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package protobuf.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Trans211TmpMsg(
|
||||||
|
@ProtoNumber(1) var msgBody: ByteArray? = null,
|
||||||
|
@ProtoNumber(2) var c2cCmd: UInt? = null,
|
||||||
|
)
|
@ -0,0 +1,11 @@
|
|||||||
|
package protobuf.message.element
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class CommonElem(
|
||||||
|
@ProtoNumber(1) val serviceType: Int? = null,
|
||||||
|
@ProtoNumber(2) val elem: ByteArray? = null,
|
||||||
|
@ProtoNumber(3) val businessType: Int? = null,
|
||||||
|
)
|
@ -0,0 +1,64 @@
|
|||||||
|
package protobuf.message.element
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class CustomFace(
|
||||||
|
@ProtoNumber(1) var guid: ByteArray? = null,
|
||||||
|
@ProtoNumber(2) var filePath: String? = null,
|
||||||
|
@ProtoNumber(3) var shortcut: String? = null,
|
||||||
|
@ProtoNumber(4) var buffer: ByteArray? = null,
|
||||||
|
@ProtoNumber(5) var flag: ByteArray? = null,
|
||||||
|
@ProtoNumber(6) var oldData: ByteArray? = null,
|
||||||
|
@ProtoNumber(7) var fileId: UInt? = null,
|
||||||
|
@ProtoNumber(8) var serverIp: UInt? = null,
|
||||||
|
@ProtoNumber(9) var serverPort: UInt? = null,
|
||||||
|
@ProtoNumber(10) var fileType: UInt? = null, // 66
|
||||||
|
@ProtoNumber(11) var signature: ByteArray? = null,
|
||||||
|
@ProtoNumber(12) var useful: UInt? = null,
|
||||||
|
@ProtoNumber(13) var md5: ByteArray? = null,
|
||||||
|
@ProtoNumber(14) var thumbUrl: String? = null,
|
||||||
|
@ProtoNumber(15) var bigUrl: String? = null,
|
||||||
|
@ProtoNumber(16) var origUrl: String? = null,
|
||||||
|
@ProtoNumber(17) var bizType: UInt? = null,
|
||||||
|
@ProtoNumber(18) var repeatIndex: UInt? = null,
|
||||||
|
@ProtoNumber(19) var repeatImage: UInt? = null,
|
||||||
|
@ProtoNumber(20) var imageType: UInt? = null,
|
||||||
|
@ProtoNumber(21) var index: UInt? = null,
|
||||||
|
@ProtoNumber(22) var width: UInt? = null,
|
||||||
|
@ProtoNumber(23) var height: UInt? = null,
|
||||||
|
@ProtoNumber(24) var source: UInt? = null,
|
||||||
|
@ProtoNumber(25) var size: UInt? = null,
|
||||||
|
@ProtoNumber(26) var origin: Boolean? = null,
|
||||||
|
@ProtoNumber(27) var thumbWidth: UInt? = null,
|
||||||
|
@ProtoNumber(28) var thumbHeight: UInt? = null,
|
||||||
|
@ProtoNumber(29) var showLen: UInt? = null,
|
||||||
|
@ProtoNumber(30) var downloadLen: UInt? = null,
|
||||||
|
@ProtoNumber(31) var url400: String? = null,
|
||||||
|
@ProtoNumber(32) var width400: UInt? = null,
|
||||||
|
@ProtoNumber(33) var height400: UInt? = null,
|
||||||
|
@ProtoNumber(34) var pbReserve: PbReserve? = null,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
@Serializable
|
||||||
|
data class PbReserve(
|
||||||
|
@ProtoNumber(1) var field1: Int? = null,
|
||||||
|
@ProtoNumber(3) var field3: Int? = null,
|
||||||
|
@ProtoNumber(4) var field4: Int? = null,
|
||||||
|
@ProtoNumber(10) var field10: Int? = null,
|
||||||
|
@ProtoNumber(21) var field21: Object1? = null,
|
||||||
|
@ProtoNumber(31) var field31: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Object1(
|
||||||
|
@ProtoNumber(1) var field1: Int? = null,
|
||||||
|
@ProtoNumber(2) var field2: String? = null,
|
||||||
|
@ProtoNumber(3) var field3: Int? = null,
|
||||||
|
@ProtoNumber(4) var field4: Int? = null,
|
||||||
|
@ProtoNumber(5) var field5: Int? = null,
|
||||||
|
@ProtoNumber(7) var md5Str: String? = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package protobuf.message.element
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ElemFlags2(
|
||||||
|
@ProtoNumber(1) var color_text_id: UInt? = null,
|
||||||
|
@ProtoNumber(2) var msg_id: ULong? = null,
|
||||||
|
@ProtoNumber(3) var whisper_session_id: UInt? = null,
|
||||||
|
@ProtoNumber(4) var ptt_change_bit: UInt? = null,
|
||||||
|
@ProtoNumber(5) var vip_status: UInt? = null,
|
||||||
|
@ProtoNumber(6) var compatible_id: UInt? = null,
|
||||||
|
@ProtoNumber(7) var rpt_insts: List<Inst>? = null,
|
||||||
|
@ProtoNumber(8) var msg_rpt_cnt: UInt? = null,
|
||||||
|
@ProtoNumber(9) var src_inst: Inst? = null,
|
||||||
|
@ProtoNumber(10) var longtitude: UInt? = null,
|
||||||
|
@ProtoNumber(11) var latitude: UInt? = null,
|
||||||
|
@ProtoNumber(12) var custom_font: UInt? = null,
|
||||||
|
@ProtoNumber(13) var pc_support_def: PcSupportDef? = null,
|
||||||
|
@ProtoNumber(14) var crm_flags: UInt? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Inst(
|
||||||
|
@ProtoNumber(1) var app_id: UInt? = null,
|
||||||
|
@ProtoNumber(2) var inst_id: UInt? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class PcSupportDef(
|
||||||
|
@ProtoNumber(1) var pc_ptl_begin: UInt? = null,
|
||||||
|
@ProtoNumber(2) var pc_ptl_end: UInt? = null,
|
||||||
|
@ProtoNumber(3) var mac_ptl_begin: UInt? = null,
|
||||||
|
@ProtoNumber(4) var mac_ptl_end: UInt? = null,
|
||||||
|
@ProtoNumber(5) var rpt_ptls_support: List<Int>? = null,
|
||||||
|
@ProtoNumber(6) var rpt_ptls_not_support: List<Int>? = null,
|
||||||
|
)
|
12
protobuf/src/main/java/protobuf/message/element/FaceMsg.kt
Normal file
12
protobuf/src/main/java/protobuf/message/element/FaceMsg.kt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package protobuf.message.element
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class FaceMsg(
|
||||||
|
@ProtoNumber(1) val index: Int? = null,
|
||||||
|
@ProtoNumber(2) var old: ByteArray? = null,
|
||||||
|
@ProtoNumber(11) var buf: ByteArray? = null,
|
||||||
|
|
||||||
|
)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user