├── .github └── ISSUE_TEMPLATE │ └── bug.yaml ├── .gitignore ├── LICENSE ├── README.md ├── arona-backend ├── .editorconfig ├── .env ├── .eslintrc.js ├── .gitattributes ├── .gitignore ├── .prettierrc ├── README.md ├── log │ ├── log │ └── log.2023-05-06 ├── nest-cli.json ├── package.json ├── pnpm-lock.yaml ├── prisma │ ├── data.db │ ├── data.db-journal │ ├── migrations │ │ ├── 20230505020148_init │ │ │ └── migration.sql │ │ ├── 20230509064430_init │ │ │ └── migration.sql │ │ └── migration_lock.toml │ └── schema.prisma ├── src │ ├── api │ │ ├── const │ │ │ └── index.ts │ │ ├── middleware │ │ │ ├── adminAccessInterceptor.ts │ │ │ ├── index.ts │ │ │ └── userAccessLogger.ts │ │ ├── types │ │ │ └── index.ts │ │ ├── utils │ │ │ └── index.ts │ │ └── v1 │ │ │ ├── controller │ │ │ └── normal │ │ │ │ └── image.ts │ │ │ └── routes │ │ │ ├── index.ts │ │ │ └── normal │ │ │ └── image.ts │ ├── command │ │ ├── announcementCommand.ts │ │ ├── exitCommand.ts │ │ └── index.ts │ ├── db │ │ └── index.ts │ ├── dict │ │ └── student │ ├── environment.d.ts │ ├── main.ts │ ├── test │ │ └── node-jieba.spec.ts │ ├── types │ │ └── index.ts │ └── utils │ │ ├── index.ts │ │ └── logger.ts ├── test │ └── jest-e2e.json ├── tsconfig.build.json └── tsconfig.json ├── arona-core ├── .editorconfig ├── .fleet │ └── themes │ │ └── dark-edited.json ├── .github │ ├── WhereIsTheGreenButton.png │ └── workflows │ │ └── Gradle CI.yml ├── .gitignore ├── build.gradle.kts ├── debug.md ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── runMirai.cmd ├── settings.gradle.kts └── src │ ├── main │ ├── kotlin │ │ └── net │ │ │ └── diyigemt │ │ │ └── arona │ │ │ ├── Arona.kt │ │ │ ├── advance │ │ │ ├── ActivityNotify.kt │ │ │ ├── AronaRemoteActionChecker.kt │ │ │ └── NGAImageTranslatePusher.kt │ │ │ ├── annotations │ │ │ ├── ConfigKey.kt │ │ │ ├── ConfigPrefix.kt │ │ │ ├── Const.kt │ │ │ ├── DTOService.kt │ │ │ ├── HideService.kt │ │ │ └── SkipSchaleDbInit.kt │ │ │ ├── command │ │ │ ├── ActivityCommand.kt │ │ │ ├── AronaConfigCommand.kt │ │ │ ├── CallMeCommand.kt │ │ │ ├── GachaConfigCommand.kt │ │ │ ├── GachaDogCommand.kt │ │ │ ├── GachaHistoryCommand.kt │ │ │ ├── GachaMultiCommand.kt │ │ │ ├── GachaSingleCommand.kt │ │ │ ├── GameNameCommand.kt │ │ │ ├── GameNameSearchCommand.kt │ │ │ ├── TarotCommand.kt │ │ │ ├── TestCommand.kt │ │ │ └── TrainerCommand.kt │ │ │ ├── config │ │ │ └── GlobalConfigProvider.kt │ │ │ ├── db │ │ │ ├── BaseDTO.kt │ │ │ ├── BaseDataBase.kt │ │ │ ├── DBConstant.kt │ │ │ ├── DataBaseProvider.kt │ │ │ ├── announcement │ │ │ │ └── RemoteActionTable.kt │ │ │ ├── data │ │ │ │ └── schaledb │ │ │ │ │ ├── CurrentData.kt │ │ │ │ │ ├── Localization.kt │ │ │ │ │ ├── MD5.kt │ │ │ │ │ ├── Raid.kt │ │ │ │ │ ├── SchaleDataBase.kt │ │ │ │ │ └── Students.kt │ │ │ ├── gacha │ │ │ │ ├── GachaCharactersTable.kt │ │ │ │ ├── GachaHistoryTable.kt │ │ │ │ ├── GachaLimitTable.kt │ │ │ │ ├── GachaPoolCharactersTable.kt │ │ │ │ └── GachaPoolsTable.kt │ │ │ ├── image │ │ │ │ └── ImageTable.kt │ │ │ ├── name │ │ │ │ ├── GameNameTable.kt │ │ │ │ └── TeacherNameTable.kt │ │ │ ├── reply │ │ │ │ ├── Labels.kt │ │ │ │ └── MessageGroups.kt │ │ │ ├── system │ │ │ │ └── SystemConfigTable.kt │ │ │ └── tarot │ │ │ │ ├── TarotRecordTable.kt │ │ │ │ └── TarotTable.kt │ │ │ ├── entity │ │ │ ├── Activity.kt │ │ │ ├── BotGroupConfig.kt │ │ │ ├── GameKeeDAO.kt │ │ │ ├── ImageResult.kt │ │ │ ├── ServerResponse.kt │ │ │ ├── TrainerOverride.kt │ │ │ └── schaleDB │ │ │ │ ├── BaseDAO.kt │ │ │ │ ├── CommonDAO.kt │ │ │ │ ├── LocalizationDAO.kt │ │ │ │ ├── RaidDAO.kt │ │ │ │ └── StudentDAO.kt │ │ │ ├── event │ │ │ ├── BaseDatabaseInitEvent.kt │ │ │ └── ConfigInitSuccessEvent.kt │ │ │ ├── extension │ │ │ ├── CommandInterceptor.kt │ │ │ ├── CommandInterceptorManager.kt │ │ │ ├── CommandResolver.kt │ │ │ └── ExitCommandInterceptor.kt │ │ │ ├── handler │ │ │ ├── GroupRepeaterHandler.kt │ │ │ └── MessageEventDispatcher.kt │ │ │ ├── interfaces │ │ │ ├── ConfigReader.kt │ │ │ ├── CoroutineFunctionProvider.kt │ │ │ └── Initialize.kt │ │ │ ├── quartz │ │ │ └── QuartzProvider.kt │ │ │ ├── remote │ │ │ ├── RemoteService.kt │ │ │ ├── RemoteServiceManager.kt │ │ │ └── action │ │ │ │ ├── AnnouncementRemoteService.kt │ │ │ │ ├── GachaPoolUpdateRemoteService.kt │ │ │ │ └── VersionUpdateRemoteService.kt │ │ │ ├── service │ │ │ ├── AronaGroupService.kt │ │ │ ├── AronaManageService.kt │ │ │ ├── AronaMessageReactService.kt │ │ │ ├── AronaQuartzService.kt │ │ │ ├── AronaReactService.kt │ │ │ ├── AronaService.kt │ │ │ └── AronaServiceManager.kt │ │ │ ├── util │ │ │ ├── ActivityUtil.kt │ │ │ ├── GachaUtil.kt │ │ │ ├── GameKeeUtil.kt │ │ │ ├── GeneralUtils.kt │ │ │ ├── ImageUtil.kt │ │ │ ├── MessageUtil.kt │ │ │ ├── MoshiUtil.kt │ │ │ ├── NetworkUtil.kt │ │ │ ├── ReflectionUtil.kt │ │ │ ├── TimeUtil.kt │ │ │ ├── WikiruUtil.kt │ │ │ ├── other │ │ │ │ └── watchservice.kt │ │ │ ├── scbaleDB │ │ │ │ ├── SchaleDBDataSyncService.kt │ │ │ │ ├── SchaleDBUtil.kt │ │ │ │ └── factories │ │ │ │ │ ├── BaseFactory.kt │ │ │ │ │ └── CalendarFactory.kt │ │ │ └── sys │ │ │ │ └── SysStatic.kt │ │ │ └── web │ │ │ ├── LoginService.kt │ │ │ ├── WebUIService.kt │ │ │ ├── api │ │ │ └── v1 │ │ │ │ ├── APIv1.md │ │ │ │ ├── Contacts.kt │ │ │ │ ├── PowerSupplyManager.kt │ │ │ │ ├── Worker.kt │ │ │ │ ├── blockly │ │ │ │ └── BlocklyAPIService.kt │ │ │ │ ├── commit │ │ │ │ └── CommitManager.kt │ │ │ │ ├── config │ │ │ │ └── ConfigService.kt │ │ │ │ ├── data │ │ │ │ └── Data.kt │ │ │ │ ├── file │ │ │ │ └── UploadManager.kt │ │ │ │ ├── message │ │ │ │ ├── ContentUnit.kt │ │ │ │ ├── DBJob.kt │ │ │ │ └── ServerResponse.kt │ │ │ │ ├── mirai │ │ │ │ └── BotsAPI.kt │ │ │ │ └── reply │ │ │ │ ├── Labels.kt │ │ │ │ └── MessageGroup.kt │ │ │ ├── blockly │ │ │ ├── BlocklyInterpreter.kt │ │ │ ├── BlocklySave.kt │ │ │ ├── BlocklyService.kt │ │ │ ├── DataTypes.kt │ │ │ ├── SaveFormat.kt │ │ │ └── SaveManager.kt │ │ │ ├── database │ │ │ ├── DBOptionService.kt │ │ │ ├── Strategy.kt │ │ │ └── security │ │ │ │ └── OptionFilter.kt │ │ │ ├── entity │ │ │ └── BotContact.kt │ │ │ └── plugins │ │ │ ├── Cros.kt │ │ │ ├── Routing.kt │ │ │ ├── Security.kt │ │ │ └── Serialization.kt │ └── resources │ │ ├── META-INF │ │ └── services │ │ │ ├── javax.script.ScriptEngineFactory │ │ │ └── net.mamoe.mirai.console.plugin.jvm.JvmPlugin │ │ └── plugin.yml │ └── test │ └── kotlin │ ├── RunMirai.kt │ ├── TestGenericJson.kt │ ├── TestSimple.kt │ ├── command │ ├── TestActivity.kt │ └── TestFetchNGA.kt │ └── quartz │ ├── TestActivityNotify.kt │ └── TestSingleTimer.kt ├── arona-doc ├── .editorconfig ├── .eslintrc.json ├── .gitattributes ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── README.md ├── components.d.ts ├── docs │ ├── .vitepress │ │ ├── config.ts │ │ ├── config │ │ │ └── menu.ts │ │ └── theme │ │ │ ├── components │ │ │ └── RegisterSW.vue │ │ │ ├── custom_style.scss │ │ │ └── index.ts │ ├── api │ │ ├── announcement.md │ │ ├── api-v1.md │ │ └── index.md │ ├── auto-imports.d.ts │ ├── command │ │ ├── auto.md │ │ ├── manual.md │ │ └── remote.md │ ├── components.d.ts │ ├── config │ │ ├── base-config.md │ │ └── database.md │ ├── docs │ │ ├── auto-imports.d.ts │ │ └── components.d.ts │ ├── guide │ │ ├── announcement.md │ │ ├── glossary.md │ │ └── what-is.md │ ├── index.md │ ├── install │ │ ├── arona.md │ │ ├── chat-command.md │ │ ├── login-bot.md │ │ ├── mirai-console.md │ │ └── qa.md │ ├── manual │ │ └── index.md │ ├── other │ │ ├── changelog.md │ │ ├── help.md │ │ └── thanks.md │ ├── public │ │ ├── empty_image.webp │ │ ├── font │ │ │ ├── ResourceHanRoundedCN-Medium.woff │ │ │ └── U-OTF-ShinMGoUpr-Medium.woff │ │ ├── icon.webp │ │ ├── image │ │ │ ├── command │ │ │ │ ├── announcment.webp │ │ │ │ ├── game-name.webp │ │ │ │ ├── image-help.webp │ │ │ │ ├── nudge.webp │ │ │ │ ├── override-name1.webp │ │ │ │ └── pool-update.webp │ │ │ ├── config │ │ │ │ ├── db-2.webp │ │ │ │ ├── db-3.webp │ │ │ │ ├── db-4.webp │ │ │ │ ├── db-5-1.webp │ │ │ │ ├── db-5-2.webp │ │ │ │ ├── db-5-3.webp │ │ │ │ ├── name-guess.webp │ │ │ │ ├── nga-cid-1.webp │ │ │ │ ├── nga-cid-2.webp │ │ │ │ ├── nga-cid-3.webp │ │ │ │ ├── nga-uid.webp │ │ │ │ └── override-name2.webp │ │ │ ├── guide │ │ │ │ ├── active-info.webp │ │ │ │ ├── activity-calendar.webp │ │ │ │ ├── activity-notify.webp │ │ │ │ ├── chapter-map.webp │ │ │ │ ├── gacha.webp │ │ │ │ ├── manage-1.webp │ │ │ │ ├── manage-2.webp │ │ │ │ ├── nga.webp │ │ │ │ ├── student.webp │ │ │ │ ├── tarot.webp │ │ │ │ └── update.webp │ │ │ └── install │ │ │ │ ├── apk.webp │ │ │ │ ├── bots.webp │ │ │ │ ├── network.webp │ │ │ │ ├── network_clear.webp │ │ │ │ ├── slider_captcha.webp │ │ │ │ ├── slider_captcha_scan.webp │ │ │ │ ├── slider_commit.webp │ │ │ │ ├── slider_content.webp │ │ │ │ ├── slider_do.webp │ │ │ │ ├── slider_second_verify.webp │ │ │ │ ├── slider_sms.webp │ │ │ │ ├── slider_success.webp │ │ │ │ └── success.webp │ │ ├── logo.webp │ │ ├── logo2.png │ │ ├── plana.webp │ │ └── robots.txt │ ├── terms │ │ ├── index.md │ │ └── others.md │ ├── types │ │ └── helper.ts │ ├── utils │ │ ├── CJKService.ts │ │ ├── anchorPositioningService.ts │ │ └── hashMatchingService.ts │ └── vite.config.ts ├── package.json ├── pnpm-lock.yaml ├── tsconfig.json └── tsconfig.node.json ├── arona-webui-frontend ├── .commitlintrc.js ├── .editorconfig ├── .env ├── .env.development ├── .env.production ├── .eslintignore ├── .eslintrc-auto-import.json ├── .eslintrc.js ├── .fleet │ └── settings.json ├── .gitattributes ├── .gitignore ├── .npmrc ├── .prettierignore ├── LICENSE ├── README.md ├── README.zh-CN.md ├── index.html ├── locales │ ├── en.json │ └── zh-cn.json ├── mock │ ├── controller │ │ ├── blockly.ts │ │ ├── config.ts │ │ ├── contact.ts │ │ ├── file.ts │ │ ├── files │ │ │ ├── neko.png │ │ │ └── rua.png │ │ ├── mirai.ts │ │ ├── ping.ts │ │ └── reply.ts │ ├── index.d.ts │ ├── index.ts │ ├── routes │ │ ├── blockly.ts │ │ ├── config.ts │ │ ├── contact.ts │ │ ├── file.ts │ │ ├── index.ts │ │ ├── mirai.ts │ │ ├── ping.ts │ │ └── reply.ts │ └── utils │ │ └── index.ts ├── package.json ├── pnpm-lock.yaml ├── presets │ └── presets.ts ├── prettier.config.js ├── public │ ├── blockly │ │ ├── blocks.json │ │ ├── toolbox.xml │ │ └── workspace.xml │ ├── favicon.svg │ ├── font │ │ ├── ResourceHanRoundedCN-Medium.ttf │ │ ├── ResourceHanRoundedCN-Medium.woff │ │ └── U-OTF-ShinMGoUpr-Medium.woff │ ├── icon.jpg │ ├── image │ │ ├── BG_CS_PR_01.jpg │ │ ├── BG_CS_PR_03.jpg │ │ ├── BG_CS_PR_05.jpg │ │ ├── BG_HQ.jpg │ │ ├── BG_View_Kivotos.jpg │ │ ├── FX_TEX_Arona_A.png │ │ ├── FX_TEX_Arona_B.png │ │ ├── FX_TEX_Arona_C.png │ │ ├── FX_TEX_Arona_Stand.png │ │ ├── FX_TEX_Triangle_02_a.png │ │ ├── arona_home_poster.jpg │ │ └── poli-light.png │ ├── raw │ │ └── dialog.json │ ├── spine │ │ ├── arona_spr.atlas │ │ ├── arona_spr.png │ │ ├── arona_spr.skel │ │ ├── arona_workpage_daytime.atlas │ │ ├── arona_workpage_daytime.png │ │ ├── arona_workpage_daytime.skel │ │ ├── arona_workpage_daytime2.png │ │ ├── arona_workpage_nighttime.atlas │ │ ├── arona_workpage_nighttime.png │ │ ├── arona_workpage_nighttime.skel │ │ └── arona_workpage_nighttime2.png │ └── video │ │ ├── arona_desk.mp4 │ │ ├── arona_look.mp4 │ │ └── arona_sleep.mp4 ├── src │ ├── App.vue │ ├── api │ │ ├── adapter │ │ │ └── localhost.ts │ │ ├── code.ts │ │ ├── http.ts │ │ ├── index.ts │ │ └── modules │ │ │ ├── blockly.ts │ │ │ ├── config.ts │ │ │ ├── contact.ts │ │ │ ├── db.ts │ │ │ ├── file.ts │ │ │ ├── mirai.ts │ │ │ └── reply.ts │ ├── assets │ │ ├── styles │ │ │ ├── dark.scss │ │ │ ├── index.scss │ │ │ ├── markdown.scss │ │ │ ├── nprogress.scss │ │ │ └── variables.scss │ │ └── svg │ │ │ └── vitecamp.svg │ ├── auto-imports.d.ts │ ├── blockly │ │ ├── BlocklyUtil.ts │ │ ├── blocks.ts │ │ ├── extensions.ts │ │ ├── generator.ts │ │ ├── images.ts │ │ ├── index.ts │ │ ├── mutators.ts │ │ ├── mutators │ │ │ ├── AbstractMutator.ts │ │ │ └── MasterBlockMutator.ts │ │ ├── serializer.ts │ │ └── widgets │ │ │ ├── DropDownView.ts │ │ │ └── DropDownView.vue │ ├── components.d.ts │ ├── components │ │ ├── EnProcess.md │ │ ├── MainAsideMenu.vue │ │ ├── MainBanner.vue │ │ ├── PageHeader.vue │ │ ├── ShadowCard.vue │ │ ├── SubPageIndex.vue │ │ ├── TheFooter.vue │ │ └── ZhProcess.md │ ├── constant │ │ ├── config.ts │ │ ├── emiterConfig.ts │ │ ├── http.ts │ │ ├── index.ts │ │ └── spine.ts │ ├── env.d.ts │ ├── interface │ │ ├── http.ts │ │ ├── index.ts │ │ └── modules │ │ │ ├── blockly.ts │ │ │ ├── config.ts │ │ │ ├── contact.ts │ │ │ ├── db.ts │ │ │ ├── gacha.ts │ │ │ ├── reply.ts │ │ │ └── setting.ts │ ├── main.ts │ ├── router │ │ ├── config │ │ │ ├── config │ │ │ │ └── index.ts │ │ │ ├── database │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ └── setting │ │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── route.async.ts │ │ ├── route.common.ts │ │ └── route.exception.ts │ ├── store │ │ ├── base.ts │ │ ├── index.ts │ │ ├── setting.ts │ │ └── type.ts │ ├── types │ │ ├── api │ │ │ ├── index.ts │ │ │ ├── params.ts │ │ │ └── response.ts │ │ ├── config.ts │ │ ├── contact.ts │ │ ├── event-type.ts │ │ ├── index.ts │ │ ├── message-type.ts │ │ ├── profile.ts │ │ └── setting.ts │ ├── utils │ │ ├── config.ts │ │ ├── config │ │ │ └── emitter.ts │ │ ├── dark.ts │ │ ├── format.ts │ │ ├── index.ts │ │ ├── message.ts │ │ ├── spine.ts │ │ ├── time.ts │ │ └── vueTools.ts │ └── views │ │ ├── config │ │ ├── ConfigIndex.vue │ │ ├── config │ │ │ ├── ConfigAronaBlockly.vue │ │ │ ├── ConfigAronaMain.vue │ │ │ ├── ConfigIndex.vue │ │ │ ├── ConfigRandomReply.vue │ │ │ ├── ConfigRandomReplyLabel.vue │ │ │ ├── components │ │ │ │ └── MainConfigDragItem.vue │ │ │ └── event │ │ │ │ └── main.ts │ │ ├── database │ │ │ ├── DatabaseGachaHistory.vue │ │ │ ├── DatabaseGachaPool.vue │ │ │ └── DatabaseIndex.vue │ │ ├── exception │ │ │ ├── 401.vue │ │ │ └── 404.vue │ │ ├── home │ │ │ └── ConfigHome.vue │ │ ├── setting │ │ │ ├── SettingAPI.vue │ │ │ └── SettingIndex.vue │ │ └── tools │ │ │ └── ToolIndex.vue │ │ └── home │ │ └── HomeIndex.vue ├── tsconfig.json ├── vite.config.ts └── windi.config.ts ├── githook └── pre-commit └── tools ├── .gitignore ├── build_student_cache.py ├── config.py ├── config ├── error.txt ├── group_download.yml ├── local_file_map.json ├── name_map_dict.txt ├── student_cache.json └── translation_dict.json ├── fetch_all_image_bili.py ├── fetch_chara_from_baha.py ├── fetch_chara_from_bili.py ├── fetch_student_info_from_ba_game_db.py ├── fill_chara_with_simple.py ├── generate_equipment_info.py ├── generate_game_db_info.py ├── generate_game_db_overview.py ├── generate_some.py ├── group_download.py ├── log_analyzer.py ├── normalize_student_by_loma.py ├── playwright ├── fake.js ├── fxxkPlaywwright.js ├── im │ ├── equipment_icon_charm_tier9.webp │ ├── equipment_icon_charm_tier9_piece.webp │ ├── equipment_icon_necklace_tier9.webp │ ├── equipment_icon_necklace_tier9_piece.webp │ ├── equipment_icon_watch_tier9.webp │ ├── equipment_icon_watch_tier9_piece.webp │ ├── item_icon_material_exskill_highlander_0.webp │ ├── item_icon_material_exskill_highlander_1.webp │ ├── item_icon_material_exskill_highlander_2.webp │ ├── item_icon_material_exskill_highlander_3.webp │ ├── item_icon_skillbook_highlander_0.webp │ ├── item_icon_skillbook_highlander_1.webp │ ├── item_icon_skillbook_highlander_2.webp │ └── item_icon_skillbook_highlander_3.webp └── init.js ├── put_all_image_into_cos.py ├── put_file_into_cos_directory.py ├── reflash_cdn.py ├── requirements.txt ├── testDiff.py ├── test_input.py ├── test_input_2.py ├── test_playwright.py ├── tools.py ├── update_game_db_info.py ├── update_main_map.py ├── update_some.py └── update_student.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Project exclude paths 2 | /.gradle/ 3 | /gradle/wrapper/gradle-wrapper.jar 4 | /build/ 5 | /.idea/ 6 | /test/ 7 | /out/ 8 | /run/ 9 | /config/ 10 | /plugins/ 11 | /debug-sandbox/* 12 | /src/test/kotlin/RunMirai.kt 13 | 14 | # Runtime files 15 | /bots/ 16 | /data/ 17 | /logs/ 18 | /plugin-libraries/ 19 | /plugin-shared-libraries/ 20 | /tools/img/ 21 | /tools/image/ 22 | /tools/raw/ 23 | /tools/__pycache__/ 24 | tools/pixiv.db 25 | tools/pixiv.py 26 | tools/pixiv.db-journal 27 | tools/skip 28 | tools/tmp.png 29 | tools/tmp2.png 30 | -------------------------------------------------------------------------------- /arona-backend/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] # 表示所有文件都要遵循 7 | indent_style = space # 缩进风格,可选配置有space和tab 8 | indent_size = 2 # 缩进大小 9 | end_of_line = lf # 换行符,可选配置有lf、cr和crlf 10 | charset = utf-8 # 编码格式,通常都是选utf-8 11 | trim_trailing_whitespace = true # 去除多余的空格 12 | insert_final_newline = true # 在尾部插入一行 13 | 14 | [*.md] # 表示仅 md 文件适用 15 | insert_final_newline = false # 在尾部插入一行 16 | trim_trailing_whitespace = false # 去除多余的空格 17 | -------------------------------------------------------------------------------- /arona-backend/.env: -------------------------------------------------------------------------------- 1 | # Environment variables declared in this file are automatically made available to Prisma. 2 | # See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema 3 | 4 | # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. 5 | # See the documentation for all the connection string options: https://pris.ly/d/connection-strings 6 | 7 | DATABASE_URL="file:./data.db" 8 | -------------------------------------------------------------------------------- /arona-backend/.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | 7 | # Declare files that will always have CRLF line endings on checkout. 8 | *.vue text eol=lf 9 | *.ts text eol=lf 10 | *.js text eol=lf 11 | *.scss text eol=lf 12 | 13 | # Denote all files that are truly binary and should not be modified. 14 | *.png binary 15 | *.jpg binary 16 | *.webp binary 17 | *.svg binary 18 | *.woff binary 19 | *.woff2 binary 20 | *.yaml binary 21 | *.json binary 22 | *.json binary 23 | -------------------------------------------------------------------------------- /arona-backend/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | pnpm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # OS 15 | .DS_Store 16 | 17 | # Tests 18 | /coverage 19 | /.nyc_output 20 | 21 | # IDEs and editors 22 | /.idea 23 | .project 24 | .classpath 25 | .c9/ 26 | *.launch 27 | .settings/ 28 | *.sublime-workspace 29 | 30 | # IDE - VSCode 31 | .vscode/* 32 | !.vscode/settings.json 33 | !.vscode/tasks.json 34 | !.vscode/launch.json 35 | !.vscode/extensions.json 36 | 37 | .env.product -------------------------------------------------------------------------------- /arona-backend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": false, 3 | "trailingComma": "all", 4 | "bracketSpacing": true, 5 | "arrowParens": "always", 6 | "endOfLine": "lf", 7 | "semi": true, 8 | "useTabs": false 9 | } -------------------------------------------------------------------------------- /arona-backend/log/log: -------------------------------------------------------------------------------- 1 | [2023-05-09T11:08:56.104] [ERROR] default - Https Error occurred: ENOENT: no such file or directory, open '/etc/letsencrypt/live/arona.diyigemt.com/privkey.pem' 2 | [2023-05-09T11:08:56.105] [INFO] default - Http Server running on http://localhost:12201 3 | [2023-05-09T11:35:36.846] [ERROR] default - Https Error abort: ENOENT: no such file or directory, open '/etc/letsencrypt/live/arona.diyigemt.com/privkey.pem' 4 | [2023-05-09T11:35:36.847] [INFO] default - Http Server running on http://localhost:12201 5 | [2023-05-09T11:59:39.457] [ERROR] default - Https Error abort: ENOENT: no such file or directory, open '/etc/letsencrypt/live/arona.diyigemt.com/privkey.pem' 6 | [2023-05-09T11:59:39.458] [INFO] default - Http Server running on http://localhost:12201 7 | -------------------------------------------------------------------------------- /arona-backend/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/nest-cli", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src", 5 | "compilerOptions": { 6 | "deleteOutDir": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /arona-backend/prisma/data.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-backend/prisma/data.db -------------------------------------------------------------------------------- /arona-backend/prisma/data.db-journal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-backend/prisma/data.db-journal -------------------------------------------------------------------------------- /arona-backend/prisma/migrations/20230505020148_init/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "users" ( 3 | "id" TEXT NOT NULL PRIMARY KEY, 4 | "version" TEXT NOT NULL DEFAULT '', 5 | "online" INTEGER NOT NULL DEFAULT 0, 6 | "lastOnline" TEXT NOT NULL DEFAULT '', 7 | "firstOnline" TEXT NOT NULL DEFAULT '' 8 | ); 9 | 10 | -- CreateTable 11 | CREATE TABLE "version" ( 12 | "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 13 | "name" TEXT NOT NULL DEFAULT '', 14 | "description" TEXT NOT NULL DEFAULT '' 15 | ); 16 | 17 | -- CreateTable 18 | CREATE TABLE "action" ( 19 | "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 20 | "action" TEXT NOT NULL DEFAULT '', 21 | "content" TEXT NOT NULL DEFAULT '', 22 | "time" TEXT NOT NULL DEFAULT '' 23 | ); 24 | 25 | -- CreateTable 26 | CREATE TABLE "image" ( 27 | "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 28 | "name" TEXT NOT NULL, 29 | "path" TEXT NOT NULL, 30 | "hash" TEXT NOT NULL, 31 | "recommendScore" INTEGER NOT NULL, 32 | "type" INTEGER NOT NULL 33 | ); 34 | -------------------------------------------------------------------------------- /arona-backend/prisma/migrations/20230509064430_init/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to drop the column `hash` on the `image` table. All the data in the column will be lost. 5 | - You are about to drop the column `path` on the `image` table. All the data in the column will be lost. 6 | - Added the required column `file` to the `image` table without a default value. This is not possible if the table is not empty. 7 | 8 | */ 9 | -- CreateTable 10 | CREATE TABLE "file" ( 11 | "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 12 | "path" TEXT NOT NULL, 13 | "hash" TEXT NOT NULL, 14 | "type" INTEGER NOT NULL 15 | ); 16 | 17 | -- RedefineTables 18 | PRAGMA foreign_keys=OFF; 19 | CREATE TABLE "new_image" ( 20 | "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 21 | "name" TEXT NOT NULL, 22 | "file" INTEGER NOT NULL, 23 | "recommendScore" INTEGER NOT NULL, 24 | "type" INTEGER NOT NULL 25 | ); 26 | INSERT INTO "new_image" ("id", "name", "recommendScore", "type") SELECT "id", "name", "recommendScore", "type" FROM "image"; 27 | DROP TABLE "image"; 28 | ALTER TABLE "new_image" RENAME TO "image"; 29 | CREATE UNIQUE INDEX "image_name_key" ON "image"("name"); 30 | PRAGMA foreign_key_check; 31 | PRAGMA foreign_keys=ON; 32 | -------------------------------------------------------------------------------- /arona-backend/prisma/migrations/migration_lock.toml: -------------------------------------------------------------------------------- 1 | # Please do not edit this file manually 2 | # It should be added in your version-control system (i.e. Git) 3 | provider = "sqlite" -------------------------------------------------------------------------------- /arona-backend/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "prisma-client-js" 6 | } 7 | 8 | datasource db { 9 | provider = "sqlite" 10 | url = env("DATABASE_URL") 11 | } 12 | 13 | model User { 14 | id String @id // uuid 唯一标识符 15 | version String @default("") // 当前版本 16 | online Int @default(0) // 在线时长 17 | lastOnline String @default("") // 上线时间 18 | firstOnline String @default("") // 第一次上线时间 19 | 20 | @@map("users") 21 | } 22 | 23 | model Version { 24 | id Int @id @default(autoincrement()) // 主键 25 | name String @default("") // 版本号 26 | description String @default("") // 简短描述 27 | 28 | @@map("version") 29 | } 30 | 31 | model Action { 32 | id Int @id @default(autoincrement()) // 主键 33 | action String @default("") // 动作类型 34 | content String @default("") // 动作内容 35 | time String @default("") // 发布时间 36 | 37 | @@map("action") 38 | } 39 | 40 | model Image { 41 | id Int @id @default(autoincrement()) // 主键 42 | name String @unique // 查找名称 唯一 43 | file Int // 对应File表的id 用于获取文件真实内容 44 | recommendScore Int // 模糊搜索优先级 45 | type Int // 图片类型 1:主线地图 2:学生攻略 3:其他杂项 46 | 47 | @@map("image") 48 | } 49 | 50 | model File { 51 | id Int @id @default(autoincrement()) // 主键 52 | path String // 本地文件位置, 相对于 file 目录 53 | hash String // 文件hash, 使用这个判断文件是否有更新 54 | type Int // 文件类型 55 | 56 | @@map("file") 57 | } 58 | -------------------------------------------------------------------------------- /arona-backend/src/api/const/index.ts: -------------------------------------------------------------------------------- 1 | export const AdminAuthToken = "token"; // 验证是否为admin 2 | export const ClientVersionHeader = "version"; // 客户端版本 3 | export const UUIDAuthHeader = "Authorization"; // uuid 4 | -------------------------------------------------------------------------------- /arona-backend/src/api/middleware/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./adminAccessInterceptor"; 2 | export * from "./userAccessLogger"; 3 | -------------------------------------------------------------------------------- /arona-backend/src/api/types/index.ts: -------------------------------------------------------------------------------- 1 | export enum HttpCode { 2 | HTTP_OK = 200, 3 | BAD_REQUEST = 400, 4 | INTERNAL_SERVER_ERROR = 500, 5 | } 6 | 7 | export interface ServerResponse { 8 | status: number; 9 | data: T; 10 | message: string; 11 | } 12 | -------------------------------------------------------------------------------- /arona-backend/src/api/v1/routes/index.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import ImageRouter from "./normal/image"; 3 | 4 | const V1Router = Router(); 5 | V1Router.use("/image", ImageRouter); 6 | 7 | export default V1Router; 8 | -------------------------------------------------------------------------------- /arona-backend/src/api/v1/routes/normal/image.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { queryImage } from "../../controller/normal/image"; 3 | 4 | const ImageRouter = Router(); 5 | ImageRouter.get("/", queryImage); 6 | export default ImageRouter; 7 | -------------------------------------------------------------------------------- /arona-backend/src/command/announcementCommand.ts: -------------------------------------------------------------------------------- 1 | import { Command } from "commander"; 2 | 3 | const AnnouncementCommand = new Command("announce") 4 | .exitOverride() 5 | .description("发布一条公告") 6 | .argument("content", "公告内容") 7 | .action((options: { content: string }) => { 8 | console.log(options); 9 | }); 10 | 11 | export default AnnouncementCommand; 12 | -------------------------------------------------------------------------------- /arona-backend/src/command/exitCommand.ts: -------------------------------------------------------------------------------- 1 | import { Command } from "commander"; 2 | import * as process from "process"; 3 | 4 | const ExitCommand = new Command("exit") 5 | .exitOverride() 6 | .description("完全退出程序") 7 | .requiredOption("-s", "二次验证参数") 8 | .action(() => { 9 | process.exit(); 10 | }); 11 | 12 | export default ExitCommand; 13 | -------------------------------------------------------------------------------- /arona-backend/src/command/index.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import { Command } from "commander"; 3 | import ExitCommand from "./exitCommand"; 4 | 5 | const CommandParser = new Command(); 6 | // eslint-disable-next-line @typescript-eslint/no-empty-function 7 | CommandParser.version("1.0.0").exitOverride(); 8 | CommandParser.addCommand(ExitCommand); 9 | 10 | export default CommandParser; 11 | -------------------------------------------------------------------------------- /arona-backend/src/db/index.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from "@prisma/client"; 2 | import { Logger } from "../utils/logger"; 3 | 4 | const Prisma = new PrismaClient({ 5 | log: [ 6 | { 7 | emit: "event", 8 | level: "query", 9 | }, 10 | ], 11 | }); 12 | 13 | Prisma.$on("query", (e) => { 14 | Logger.info(e.query); 15 | Logger.info(e.params); 16 | Logger.info(e.timestamp); 17 | }); 18 | 19 | export default Prisma; 20 | -------------------------------------------------------------------------------- /arona-backend/src/dict/student: -------------------------------------------------------------------------------- 1 | 歌原 2 | 伊织 3 | 佐仓 -------------------------------------------------------------------------------- /arona-backend/src/environment.d.ts: -------------------------------------------------------------------------------- 1 | declare module "process" { 2 | global { 3 | namespace NodeJS { 4 | interface ProcessEnv { 5 | ADMIN_SECRET: string; 6 | } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /arona-backend/src/test/node-jieba.spec.ts: -------------------------------------------------------------------------------- 1 | import * as nodejieba from "nodejieba"; 2 | import PinyinMatch from "pinyin-match"; 3 | import { toPinyin } from "../utils"; 4 | 5 | const cut = nodejieba.cut("白亚的预告函~虚饰之馆与美学的所在~"); 6 | console.log(cut); 7 | const match = PinyinMatch.match("黑色的", toPinyin(cut[0])); 8 | test("", () => { 9 | expect(match).toBe(true); 10 | }); 11 | -------------------------------------------------------------------------------- /arona-backend/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export type ImageFuzzySearchCacheItem = { 2 | id: number; 3 | name: string; 4 | recommendScore: number; 5 | }; 6 | 7 | export type ImageItem = { 8 | name: string; 9 | path: string; 10 | hash: string; 11 | type: number; 12 | }; 13 | -------------------------------------------------------------------------------- /arona-backend/src/utils/logger.ts: -------------------------------------------------------------------------------- 1 | import log4js from "log4js"; 2 | 3 | log4js.configure({ 4 | appenders: { 5 | file: { 6 | type: "dateFile", 7 | filename: "./log/log", 8 | keepFileExt: true, 9 | numBackups: 365, 10 | }, 11 | console: { 12 | type: "console", 13 | }, 14 | }, 15 | categories: { 16 | default: { 17 | appenders: ["file", "console"], 18 | level: "debug", 19 | }, 20 | database: { 21 | appenders: ["file"], 22 | level: "debug", 23 | }, 24 | }, 25 | }); 26 | 27 | export const DatabaseLogger = log4js.getLogger("database"); 28 | export const Logger = log4js.getLogger(); 29 | -------------------------------------------------------------------------------- /arona-backend/test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /arona-backend/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /arona-backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": false, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "es6", 10 | "sourceMap": true, 11 | "esModuleInterop": true, 12 | "outDir": "./dist", 13 | "baseUrl": ".", 14 | "incremental": true, 15 | "skipLibCheck": true, 16 | "forceConsistentCasingInFileNames": false, 17 | "noFallthroughCasesInSwitch": false, 18 | "strict": true, 19 | /* Enable all strict type-checking options. */ 20 | "noImplicitAny": true, 21 | /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 22 | "strictNullChecks": true, 23 | /* When type checking, take into account 'null' and 'undefined'. */ 24 | "strictFunctionTypes": true, 25 | /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 26 | "strictBindCallApply": true, 27 | /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 28 | "strictPropertyInitialization": true, 29 | /* Check for class properties that are declared but not set in the constructor. */ 30 | "noImplicitThis": true, 31 | /* Enable error reporting when 'this' is given the type 'any'. */ 32 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 33 | "alwaysStrict": true, 34 | }, 35 | } 36 | -------------------------------------------------------------------------------- /arona-core/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{kt, kts}] 2 | max_line_length = 120 3 | tab_width = 2 4 | ij_continuation_indent_size = 2 5 | indent_size = 2 -------------------------------------------------------------------------------- /arona-core/.github/WhereIsTheGreenButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-core/.github/WhereIsTheGreenButton.png -------------------------------------------------------------------------------- /arona-core/.github/workflows/Gradle CI.yml: -------------------------------------------------------------------------------- 1 | name: Gradle CI 2 | 3 | # Controls when the action will run. 4 | on: 5 | # Triggers the workflow on push and pull request events but only for the master branch 6 | push: 7 | branches: 8 | - master 9 | pull_request: 10 | branches: 11 | - master 12 | 13 | # Allows to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | jobs: 17 | 18 | build: 19 | 20 | name: Gradle-Build 21 | 22 | # The type of runner that the job will run on 23 | runs-on: ubuntu-20.04 24 | 25 | # Steps represent a sequence of tasks that will be executed as part of the job 26 | steps: 27 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 28 | - name: Checkout 29 | uses: actions/checkout@v2 30 | 31 | # Setup JDK 32 | - name: Setup Java JDK 33 | uses: actions/setup-java@v1.4.3 34 | with: 35 | java-version: 11 36 | 37 | # Validate Gradle Wrapper 38 | - name: Gradle Wrapper Validation 39 | uses: gradle/wrapper-validation-action@v1.0.3 40 | 41 | # Build 42 | - name: Make gradlew executable 43 | run: chmod +x ./gradlew 44 | - name: Build with Gradle 45 | run: ./gradlew build 46 | -------------------------------------------------------------------------------- /arona-core/.gitignore: -------------------------------------------------------------------------------- 1 | # Project exclude paths 2 | /.gradle/ 3 | /gradle/wrapper/gradle-wrapper.jar 4 | /build/ 5 | /.idea/ 6 | /test/ 7 | /out/ 8 | /run/ 9 | /bin/ 10 | /config/ 11 | /plugins/ 12 | /debug-sandbox/* 13 | deploy.cmd 14 | 15 | # Runtime files 16 | /bots/ 17 | /data/ 18 | /logs/ 19 | /debug/ 20 | /plugin-libraries/ 21 | /plugin-shared-libraries/ 22 | /tools/img/ 23 | /tools/image/ 24 | /tools/__pycache__/ 25 | tools/pixiv.db 26 | tools/pixiv.py 27 | tools/pixiv.db-journal 28 | tools/skip 29 | -------------------------------------------------------------------------------- /arona-core/debug.md: -------------------------------------------------------------------------------- 1 | # 调试 2 | 3 | 由于Arona-Core中使用了基于Ktor2.1.2的Web服务,与mirai-core-api官方使用的ktor-client-core-jvm1.6.7冲突。所以此项目无法运行在单元测试环境中,只能打包放进mcl中以远程调试的方式进行。 4 | 5 | 6 | 7 | ## 调试环境搭建 8 | 9 | 1. 在arona-core根目录中找到deploy.cmd,修改以下内容然后保存: 10 | 11 | ```shell 12 | ::你的MCL根目录 13 | set MCL_PATH="path\to\mcl" 14 | ``` 15 | 16 | 2. 在IDEA中新建一个远程调试配置(Remote JVM Debug),调试模式选择Attach to remote JVM(默认),端口选择5005(默认) 17 | 18 | 3. 修改代码和下断点 19 | 20 | 4. 找到Gradle task: buildAndDeploy运行(此任务会编译mirai插件并将输出的jar包和启动脚本复制粘贴到mcl中) 21 | 22 | 5. 控制台进入mcl根目录 23 | 24 | 6. 运行runMirai.cmd,等待控制台输出以下内容: 25 | 26 | ```shell 27 | Listening for transport dt_socket at address: 5005 28 | ``` 29 | 30 | 7. 启动IDEA配置好的远程调试 31 | 32 | 33 | 34 | ## 附加命令 35 | 36 | Windows端适用 37 | 38 | #### 查找占用5005端口的进程 39 | 40 | ```shell 41 | netstat -ano|findstr "5005" 42 | ``` 43 | 44 | #### 杀掉PID进程 45 | 46 | ```shell 47 | taskkill /T /F /PID 12345 48 | ``` 49 | 50 | -------------------------------------------------------------------------------- /arona-core/gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.code.style=official -------------------------------------------------------------------------------- /arona-core/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /arona-core/runMirai.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | ::调试端口,默认5005 4 | set DEBUG_PORT=5005 5 | 6 | java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=%DEBUG_PORT% -jar mcl.jar -------------------------------------------------------------------------------- /arona-core/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "net.diyigemt.arona-arona" -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/annotations/ConfigKey.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.annotations 2 | 3 | /** 4 | * 通过此注解获得在GlobalConfig中对应的key 5 | */ 6 | @Target(AnnotationTarget.PROPERTY) 7 | annotation class ConfigKey( 8 | val value: String 9 | ) 10 | -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/annotations/ConfigPrefix.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.annotations 2 | 3 | /** 4 | * 通过此注解获得该类在GlobalConfig中对应的key前缀 5 | */ 6 | @Target(AnnotationTarget.CLASS) 7 | annotation class ConfigPrefix( 8 | val value: String 9 | ) 10 | -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/annotations/Const.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.annotations 2 | 3 | /** 4 | *@Author hjn 5 | *@Create 2022/10/24 6 | * 拥有此注解的Config成员不许修改 7 | */ 8 | annotation class Const 9 | -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/annotations/DTOService.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.annotations 2 | 3 | /** 4 | *@Author hjn 5 | *@Create 2022/10/25 6 | * 在数据类添加此注解以作为DTO供数据库接口使用 7 | */ 8 | @Target(AnnotationTarget.CLASS) 9 | annotation class DTOService 10 | -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/annotations/HideService.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.annotations 2 | 3 | /** 4 | * 在自动注册控制台权限时默认隐藏 5 | */ 6 | @Target(AnnotationTarget.CLASS) 7 | @Retention(AnnotationRetention.RUNTIME) 8 | annotation class HideService 9 | -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/annotations/SkipSchaleDbInit.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.annotations 2 | 3 | /** 4 | * 用于数据库初始化, 加上这个注解的表不会被BaseDatabase创建 5 | */ 6 | annotation class SkipSchaleDbInit 7 | -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/command/GachaDogCommand.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.command 2 | 3 | import net.diyigemt.arona.Arona 4 | import net.diyigemt.arona.service.AronaGroupService 5 | import net.diyigemt.arona.util.GachaUtil 6 | import net.diyigemt.arona.util.GeneralUtils 7 | import net.mamoe.mirai.console.command.MemberCommandSenderOnMessage 8 | import net.mamoe.mirai.console.command.SimpleCommand 9 | 10 | object GachaDogCommand : SimpleCommand( 11 | Arona, "gacha_dog", "狗叫", 12 | description = "查看抽出pick的人" 13 | ), AronaGroupService { 14 | 15 | @Handler 16 | suspend fun MemberCommandSenderOnMessage.gachaDog() { 17 | val dogCall = GachaUtil.getDogCall(subject.id).filter { it.dog != 0 } 18 | if (dogCall.isEmpty()) { 19 | subject.sendMessage("还没有老师抽出来哦") 20 | return 21 | } 22 | var ss = "狗叫排行:\n" 23 | dogCall.map { 24 | val teacherName = GeneralUtils.queryTeacherNameFromDB(subject, subject[it.id.value]!!) 25 | "${teacherName}(${it.id.value}): ${it.dog}抽" 26 | }.forEachIndexed { index, s -> 27 | ss += "${index + 1}. $s\n" 28 | } 29 | subject.sendMessage(ss.subSequence(0, ss.length - 1).toString()) 30 | } 31 | 32 | override val id: Int = 6 33 | override val name: String = "抽卡狗叫查询" 34 | override var isGlobal: Boolean = false 35 | 36 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/command/GachaHistoryCommand.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.command 2 | 3 | import net.diyigemt.arona.Arona 4 | import net.diyigemt.arona.service.AronaGroupService 5 | import net.diyigemt.arona.util.GachaUtil 6 | import net.diyigemt.arona.util.GeneralUtils.queryTeacherNameFromDB 7 | import net.mamoe.mirai.console.command.MemberCommandSenderOnMessage 8 | import net.mamoe.mirai.console.command.SimpleCommand 9 | 10 | object GachaHistoryCommand : SimpleCommand( 11 | Arona, "gacha_history", "历史", 12 | description = "抽卡历史记录" 13 | ), AronaGroupService { 14 | 15 | @Handler 16 | suspend fun MemberCommandSenderOnMessage.gachaHistory() { 17 | val history = GachaUtil.getHistoryAll(subject.id) 18 | if (history.isEmpty()) { 19 | subject.sendMessage("还没有记录哦") 20 | return 21 | } 22 | var ss = "历史排行:\n" 23 | history 24 | .map { 25 | val teacherName = queryTeacherNameFromDB(subject, subject[it.id.value]!!) 26 | val rate = if (it.count3 == 0) 0 else it.points / it.count3 27 | "${teacherName}(${it.id.value}): ${it.points}抽/${it.count3}个3星 = $rate" 28 | } 29 | .subList(0, if (history.size > 6) 6 else history.size) 30 | .forEachIndexed { index, s -> 31 | ss += "${index + 1}. $s\n" 32 | } 33 | subject.sendMessage(ss.subSequence(0, ss.length - 1).toString()) 34 | } 35 | 36 | override val id: Int = 7 37 | override val name: String = "抽卡历史查询" 38 | override var isGlobal: Boolean = false 39 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/command/TestCommand.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.command 2 | 3 | import net.diyigemt.arona.Arona 4 | import net.diyigemt.arona.service.AronaGroupService 5 | import net.mamoe.mirai.console.command.MemberCommandSenderOnMessage 6 | import net.mamoe.mirai.console.command.SimpleCommand 7 | 8 | object TestCommand: SimpleCommand( 9 | Arona, "arona_test_01", description = "测试指令转发" 10 | ), AronaGroupService { 11 | @Handler 12 | suspend fun MemberCommandSenderOnMessage.arona_test_01() { 13 | subject.sendMessage("测试") 14 | } 15 | 16 | override val id: Int = 30 17 | override val name: String = "指令转发" 18 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/BaseDTO.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db 2 | 3 | import org.jetbrains.exposed.sql.ResultRow 4 | 5 | /** 6 | *@Author hjn 7 | *@Create 2022/10/25 8 | */ 9 | interface BaseDTO { 10 | fun toModel(results : List) : List 11 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/DBConstant.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db 2 | 3 | object DBConstant { 4 | 5 | private const val GLOBAL_DB_NAME: String = "arona.db" 6 | private const val SCHALE_DB_NAME: String = "schale.db" 7 | 8 | val dbNameList = mutableListOf(GLOBAL_DB_NAME, SCHALE_DB_NAME) 9 | } 10 | 11 | enum class DB{ 12 | DEFAULT, 13 | DATA 14 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/announcement/RemoteActionTable.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.announcement 2 | 3 | import org.jetbrains.exposed.dao.LongEntity 4 | import org.jetbrains.exposed.dao.LongEntityClass 5 | import org.jetbrains.exposed.dao.id.EntityID 6 | import org.jetbrains.exposed.dao.id.LongIdTable 7 | import org.jetbrains.exposed.sql.Column 8 | 9 | /** 10 | * 保存已发送的公告id 11 | */ 12 | object RemoteActionTable: LongIdTable(name = "RemoteAction") { 13 | val aid: Column = long("aid") 14 | } 15 | 16 | class RemoteActionModel(id: EntityID): LongEntity(id) { 17 | companion object: LongEntityClass(RemoteActionTable) 18 | var aid by RemoteActionTable.aid 19 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/data/schaledb/CurrentData.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.data.schaledb 2 | 3 | import net.diyigemt.arona.annotations.SkipSchaleDbInit 4 | import org.jetbrains.exposed.sql.Column 5 | import org.jetbrains.exposed.sql.Table 6 | 7 | /** 8 | *@Author hjn 9 | *@Create 2022/8/28 10 | */ 11 | @SkipSchaleDbInit 12 | object CurrentData : Table("CurrentData") { 13 | val value : Column = integer("value") 14 | val type : Column = varchar("type", 10) 15 | val server : Column = varchar("server", 10) 16 | val start : Column = long("start") 17 | val end : Column = long("end") 18 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/data/schaledb/Localization.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.data.schaledb 2 | 3 | import net.diyigemt.arona.annotations.SkipSchaleDbInit 4 | import org.jetbrains.exposed.sql.Column 5 | import org.jetbrains.exposed.sql.Table 6 | 7 | /** 8 | *@Author hjn 9 | *@Create 2022/8/28 10 | */ 11 | @SkipSchaleDbInit 12 | object Localization : Table("Localization"){ 13 | val tag : Column = varchar("tag", 10) 14 | val eventID : Column = integer("eventID") 15 | val value : Column = varchar("value", 100) 16 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/data/schaledb/MD5.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.data.schaledb 2 | 3 | import net.diyigemt.arona.annotations.SkipSchaleDbInit 4 | import org.jetbrains.exposed.sql.Column 5 | import org.jetbrains.exposed.sql.Table 6 | 7 | /** 8 | *@Author hjn 9 | *@Create 2022/8/28 10 | */ 11 | @SkipSchaleDbInit 12 | object MD5 : Table("MD5"){ 13 | val name : Column = varchar("name", 20) 14 | val remote : Column = varchar("source", 10) 15 | val md5 : Column = varchar("md5", 32) 16 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/data/schaledb/Raid.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.data.schaledb 2 | 3 | import net.diyigemt.arona.annotations.DTOService 4 | import net.diyigemt.arona.annotations.SkipSchaleDbInit 5 | import net.diyigemt.arona.db.BaseDTO 6 | import org.jetbrains.exposed.sql.Column 7 | import org.jetbrains.exposed.sql.ResultRow 8 | import org.jetbrains.exposed.sql.Table 9 | 10 | /** 11 | *@Author hjn 12 | *@Create 2022/8/28 13 | */ 14 | @DTOService 15 | @SkipSchaleDbInit 16 | object Raid : Table("Raid") { 17 | val Id : Column = integer("Id") 18 | val IsReleased : Column = bool("IsReleased") 19 | val NameCn : Column = varchar("NameCn", 20) 20 | val CurrentJPN : Column = varchar("CurrentJPN", 20) 21 | val CurrentGLB : Column = varchar("CurrentGLB", 20) 22 | 23 | data class RaidDTO( 24 | val Id : Int = 0, 25 | val IsReleased : Boolean = false, 26 | val NameCn : String = "", 27 | val CurrentGLB : String = "", 28 | val CurrentJPN : String = "" 29 | ) : BaseDTO { 30 | override fun toModel(results: List): List { 31 | val res : MutableList = mutableListOf() 32 | results.forEach { 33 | res.add(RaidDTO(it[Raid.Id], it[Raid.IsReleased], it[Raid.NameCn], it[Raid.CurrentGLB], it[Raid.CurrentJPN])) 34 | } 35 | 36 | return res 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/data/schaledb/SchaleDataBase.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.data.schaledb 2 | 3 | import net.diyigemt.arona.Arona 4 | import net.diyigemt.arona.db.DB 5 | import net.diyigemt.arona.db.DataBaseProvider 6 | import org.jetbrains.exposed.sql.SchemaUtils 7 | 8 | /** 9 | *@Author hjn 10 | *@Create 2022/8/26 11 | */ 12 | object SchaleDataBase { 13 | fun init(){ 14 | kotlin.runCatching { 15 | initDataBase() 16 | }.onFailure { 17 | Arona.warning(it.toString()) 18 | Arona.warning("数据库修改操作失败,删除当前库重建") 19 | deleteDataBase() 20 | initDataBase() 21 | } 22 | } 23 | 24 | private fun initDataBase(){ 25 | DataBaseProvider.query(DB.DATA.ordinal) { 26 | SchemaUtils.createMissingTablesAndColumns( 27 | MD5, 28 | 29 | Students, 30 | Localization, 31 | Raid, 32 | CurrentData 33 | ) 34 | } 35 | } 36 | 37 | private fun deleteDataBase(){ 38 | DataBaseProvider.query(DB.DATA.ordinal) { 39 | SchemaUtils.drop( 40 | MD5, 41 | 42 | Students, 43 | Localization, 44 | Raid, 45 | CurrentData) 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/data/schaledb/Students.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.data.schaledb 2 | 3 | import net.diyigemt.arona.annotations.SkipSchaleDbInit 4 | import org.jetbrains.exposed.sql.Column 5 | import org.jetbrains.exposed.sql.Table 6 | 7 | /** 8 | *@Author hjn 9 | *@Create 2022/8/24 10 | */ 11 | @SkipSchaleDbInit 12 | object Students : Table("Students") { 13 | val studentID: Column = integer("studentID") 14 | val name: Column = varchar("name", 15) 15 | val birthday: Column = varchar("birthday", 5) 16 | 17 | override val primaryKey: PrimaryKey = PrimaryKey(studentID) 18 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/gacha/GachaLimitTable.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.gacha 2 | 3 | import net.diyigemt.arona.annotations.DTOService 4 | import net.diyigemt.arona.db.BaseDTO 5 | import org.jetbrains.exposed.dao.LongEntity 6 | import org.jetbrains.exposed.dao.LongEntityClass 7 | import org.jetbrains.exposed.dao.id.EntityID 8 | import org.jetbrains.exposed.dao.id.IdTable 9 | import org.jetbrains.exposed.sql.Column 10 | import org.jetbrains.exposed.sql.ResultRow 11 | 12 | @DTOService 13 | object GachaLimitTable: IdTable(name = "GachaLimit") { 14 | override val id: Column> = long("qq").entityId() 15 | val group: Column = long("group") 16 | val count: Column = integer("count") 17 | 18 | override val primaryKey: PrimaryKey = PrimaryKey(id, group) 19 | 20 | data class GachaLimitDTO( 21 | val group: Long = 0, 22 | val count: Int = 0 23 | ): BaseDTO{ 24 | override fun toModel(results: List): List { 25 | val res: MutableList = mutableListOf() 26 | results.forEach { 27 | res.add( 28 | GachaLimitDTO( 29 | it[GachaLimitTable.group], 30 | it[GachaLimitTable.count] 31 | ) 32 | ) 33 | } 34 | 35 | return res 36 | } 37 | } 38 | } 39 | 40 | class GachaLimit(id: EntityID): LongEntity(id) { 41 | companion object: LongEntityClass(GachaLimitTable) 42 | var group by GachaLimitTable.group 43 | var count by GachaLimitTable.count 44 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/gacha/GachaPoolCharactersTable.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.gacha 2 | 3 | import net.diyigemt.arona.annotations.DTOService 4 | import net.diyigemt.arona.db.BaseDTO 5 | import org.jetbrains.exposed.dao.IntEntity 6 | import org.jetbrains.exposed.dao.IntEntityClass 7 | import org.jetbrains.exposed.dao.id.EntityID 8 | import org.jetbrains.exposed.dao.id.IntIdTable 9 | import org.jetbrains.exposed.sql.ResultRow 10 | 11 | @DTOService 12 | object GachaPoolCharactersTable: IntIdTable(name = "GachaPoolCharacters") { 13 | val poolId = reference("pool_id", GachaPoolsTable.id) 14 | val characterId = reference("character_id", GachaCharactersTable.id) 15 | 16 | data class GachaPoolCharactersDTO( 17 | val poolId: Int = 0, 18 | val characterId: Int = 0 19 | ): BaseDTO{ 20 | override fun toModel(results: List): List { 21 | val res: MutableList = mutableListOf() 22 | 23 | results.forEach { 24 | res.add( 25 | GachaPoolCharactersDTO( 26 | it[GachaPoolCharactersTable.poolId].value, 27 | it[GachaPoolCharactersTable.characterId].value, 28 | ) 29 | ) 30 | } 31 | 32 | return res 33 | } 34 | } 35 | } 36 | 37 | class GachaPoolCharacters(id: EntityID) : IntEntity(id) { 38 | companion object: IntEntityClass(GachaPoolCharactersTable) 39 | var poolId by GachaPoolCharactersTable.poolId 40 | var characterId by GachaPoolCharactersTable.characterId 41 | } 42 | -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/gacha/GachaPoolsTable.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.gacha 2 | 3 | import net.diyigemt.arona.annotations.DTOService 4 | import net.diyigemt.arona.db.BaseDTO 5 | import org.jetbrains.exposed.dao.IntEntity 6 | import org.jetbrains.exposed.dao.IntEntityClass 7 | import org.jetbrains.exposed.dao.id.EntityID 8 | import org.jetbrains.exposed.dao.id.IntIdTable 9 | import org.jetbrains.exposed.sql.Column 10 | import org.jetbrains.exposed.sql.ResultRow 11 | 12 | @DTOService 13 | object GachaPoolsTable: IntIdTable(name = "GachaPools") { 14 | val name: Column = varchar("name", 50) 15 | 16 | data class GachaPoolsDTO( 17 | val id: Int = 0, 18 | val name: String = "" 19 | ): BaseDTO{ 20 | override fun toModel(results: List): List { 21 | val res: MutableList = mutableListOf() 22 | results.forEach{ 23 | res.add( 24 | GachaPoolsDTO( 25 | it[GachaPoolsTable.id].value, 26 | it[GachaPoolsTable.name] 27 | ) 28 | ) 29 | } 30 | return res 31 | } 32 | } 33 | } 34 | 35 | class GachaPools(id: EntityID) : IntEntity(id) { 36 | companion object: IntEntityClass(GachaPoolsTable) 37 | var name by GachaPoolsTable.name 38 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/image/ImageTable.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.image 2 | 3 | import org.jetbrains.exposed.dao.LongEntity 4 | import org.jetbrains.exposed.dao.LongEntityClass 5 | import org.jetbrains.exposed.dao.id.EntityID 6 | import org.jetbrains.exposed.dao.id.LongIdTable 7 | import org.jetbrains.exposed.sql.Column 8 | 9 | object ImageTable: LongIdTable(name = "Image") { 10 | val name: Column = char("name", 255) 11 | val path: Column = char("path", 255) 12 | val hash: Column = char("hash", 255) 13 | val type: Column = integer("type") 14 | } 15 | 16 | class ImageTableModel(id: EntityID): LongEntity(id) { 17 | companion object: LongEntityClass(ImageTable) 18 | var name by ImageTable.name 19 | var path by ImageTable.path 20 | var hash by ImageTable.hash 21 | var type by ImageTable.type 22 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/name/GameNameTable.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.name 2 | 3 | import net.diyigemt.arona.annotations.DTOService 4 | import net.diyigemt.arona.db.BaseDTO 5 | import org.jetbrains.exposed.dao.LongEntity 6 | import org.jetbrains.exposed.dao.LongEntityClass 7 | import org.jetbrains.exposed.dao.id.EntityID 8 | import org.jetbrains.exposed.dao.id.IdTable 9 | import org.jetbrains.exposed.sql.Column 10 | import org.jetbrains.exposed.sql.ResultRow 11 | 12 | @DTOService 13 | object GameNameTable: IdTable(name = "GameName") { 14 | override val id: Column> = long("qq").entityId() 15 | val name: Column = char("name", 50) 16 | 17 | override val primaryKey: PrimaryKey = PrimaryKey(id) 18 | 19 | data class GameNameDTO( 20 | val id: Long = 0, 21 | val name: String = "" 22 | ): BaseDTO{ 23 | override fun toModel(results: List): List { 24 | val res: MutableList = mutableListOf() 25 | 26 | results.forEach { 27 | res.add( 28 | GameNameDTO( 29 | it[GameNameTable.id].value, 30 | it[GameNameTable.name] 31 | ) 32 | ) 33 | } 34 | 35 | return res 36 | } 37 | } 38 | } 39 | 40 | class GameName(id: EntityID): LongEntity(id) { 41 | companion object: LongEntityClass(GameNameTable) 42 | var name by GameNameTable.name 43 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/name/TeacherNameTable.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.name 2 | 3 | import org.jetbrains.exposed.dao.LongEntity 4 | import org.jetbrains.exposed.dao.LongEntityClass 5 | import org.jetbrains.exposed.dao.id.EntityID 6 | import org.jetbrains.exposed.dao.id.IdTable 7 | import org.jetbrains.exposed.sql.Column 8 | 9 | object TeacherNameTable: IdTable(name = "TeacherName") { 10 | override val id: Column> = long("qq").entityId() 11 | val group: Column = long("group") 12 | val name: Column = char("name", 20) 13 | 14 | override val primaryKey: PrimaryKey = PrimaryKey(id, group) 15 | } 16 | 17 | class TeacherName(id: EntityID): LongEntity(id) { 18 | companion object: LongEntityClass(TeacherNameTable) 19 | var group by TeacherNameTable.group 20 | var name by TeacherNameTable.name 21 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/reply/Labels.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.reply 2 | 3 | import kotlinx.serialization.Serializable 4 | import org.jetbrains.exposed.dao.id.IntIdTable 5 | import org.jetbrains.exposed.sql.Column 6 | 7 | /** 8 | *@Author hjn 9 | *@Create 2023/2/19 10 | */ 11 | object Labels: IntIdTable("Labels") { 12 | val value: Column = varchar("tagName", 255) 13 | val weight: Column = integer("weight") 14 | } 15 | 16 | @Serializable 17 | data class LabelItem( 18 | val id: Int, 19 | val value: String, 20 | val weight: Int, 21 | ) -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/reply/MessageGroups.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.reply 2 | 3 | import com.squareup.moshi.JsonClass 4 | import kotlinx.serialization.Serializable 5 | import org.jetbrains.exposed.dao.id.IntIdTable 6 | import org.jetbrains.exposed.sql.Column 7 | 8 | /** 9 | *@Author hjn 10 | *@Create 2023/2/21 11 | */ 12 | object MessageGroups: IntIdTable("MessageGroups") { 13 | val content: Column = varchar("content", 1000000) 14 | val weight: Column = integer("weight") 15 | val labels: Column = varchar("labels", 255) 16 | } 17 | 18 | @Serializable 19 | data class MessageGroup( 20 | val id: Int, 21 | val content: List, 22 | val weight: Int, 23 | val label: List 24 | ) 25 | 26 | @Serializable 27 | @JsonClass(generateAdapter = true) 28 | data class ContentItem( 29 | val type: MessageKind, 30 | val content: String 31 | ) 32 | 33 | enum class MessageKind { 34 | String, Image 35 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/system/SystemConfigTable.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.system 2 | 3 | import org.jetbrains.exposed.dao.LongEntity 4 | import org.jetbrains.exposed.dao.LongEntityClass 5 | import org.jetbrains.exposed.dao.id.EntityID 6 | import org.jetbrains.exposed.dao.id.LongIdTable 7 | import org.jetbrains.exposed.sql.Column 8 | 9 | object SystemConfigTable: LongIdTable(name = "SystemConfig") { 10 | val key: Column = char("key", 255) 11 | val value: Column = char("value", 255) 12 | } 13 | 14 | class SystemConfigTableModel(id: EntityID): LongEntity(id) { 15 | companion object: LongEntityClass(SystemConfigTable) 16 | var key by SystemConfigTable.key 17 | var value by SystemConfigTable.value 18 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/tarot/TarotRecordTable.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.tarot 2 | 3 | import org.jetbrains.exposed.dao.LongEntity 4 | import org.jetbrains.exposed.dao.LongEntityClass 5 | import org.jetbrains.exposed.dao.id.EntityID 6 | import org.jetbrains.exposed.dao.id.IdTable 7 | import org.jetbrains.exposed.sql.Column 8 | 9 | object TarotRecordTable: IdTable(name = "TarotRecord") { 10 | override val id: Column> = long("qq").entityId() 11 | val group: Column = long("group") 12 | val day: Column = integer("day") 13 | val tarot: Column = integer("tarot") 14 | val positive: Column = bool("positive") 15 | 16 | override val primaryKey: PrimaryKey = PrimaryKey(id, group) 17 | } 18 | 19 | class TarotRecord(id: EntityID): LongEntity(id) { 20 | companion object: LongEntityClass(TarotRecordTable) 21 | var group by TarotRecordTable.group 22 | var day by TarotRecordTable.day 23 | var tarot by TarotRecordTable.tarot 24 | var positive by TarotRecordTable.positive 25 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/db/tarot/TarotTable.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.db.tarot 2 | 3 | import org.jetbrains.exposed.dao.IntEntity 4 | import org.jetbrains.exposed.dao.IntEntityClass 5 | import org.jetbrains.exposed.dao.id.EntityID 6 | import org.jetbrains.exposed.dao.id.IntIdTable 7 | import org.jetbrains.exposed.sql.Column 8 | 9 | object TarotTable: IntIdTable(name = "Tarot") { 10 | val name: Column = varchar("name", 30) 11 | val positive: Column = text("positive") 12 | val negative: Column = text("negative") 13 | 14 | } 15 | 16 | class Tarot(id: EntityID) : IntEntity(id) { 17 | companion object: IntEntityClass(TarotTable) 18 | 19 | val name by TarotTable.name 20 | val positive by TarotTable.positive 21 | val negative by TarotTable.negative 22 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/entity/Activity.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.entity 2 | 3 | data class Activity( 4 | var content: String, 5 | var time: String, 6 | var type: ActivityType = ActivityType.NULL, 7 | var serverLocale: ServerLocale = ServerLocale.JP, 8 | ) 9 | 10 | enum class ServerLocale(val serverName: String, val dbName: String) { 11 | JP("日服", "JPN"), GLOBAL("国际服", "GLB") 12 | } 13 | 14 | enum class ActivityType(val level: Int) { 15 | NULL(1), 16 | N2_3(1), 17 | H2_3(1), 18 | SPECIAL_DROP(1), // 特别作战(钱本经验本) 19 | WANTED_DROP(1), // 悬赏通缉 20 | COLLEGE_EXCHANGE_DROP(1), // 学院交流 21 | SCHEDULE(1), // 课程表 22 | DECISIVE_BATTLE(3), // 总力战 23 | JOINT_EXERCISES(1), // 合同火力演习 24 | PICK_UP(3), // 卡池 25 | KABALA(2), // 十字神明特殊活动 26 | MAINTENANCE(4), // 维护 27 | ACTIVITY(2), // 普通活动 28 | BIRTHDAY(5) //生日 29 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/entity/BotGroupConfig.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.entity 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | /** 6 | * 存储Bot与Group的对应关系 7 | * 8 | * 一个Bot可以对应多个群, 单个群只能关联一个Bot 9 | * 10 | * 可能以后会支持细化到bot和群的配置文件吧, 现在只细化到群 11 | */ 12 | @Serializable 13 | data class BotGroupConfig ( 14 | val bot: Long, 15 | val groups: List 16 | ) -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/entity/GameKeeDAO.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.entity 2 | 3 | /** 4 | *@Author hjn 5 | *@Create 2022/7/22 6 | */ 7 | data class GameKeeDAO( 8 | val code : Int, 9 | val msg : String, 10 | val data : List, 11 | val meta : Meta 12 | ) 13 | 14 | data class Data( 15 | val id : Int, 16 | var title : String, 17 | val link_url : String, 18 | val picture : String, 19 | val description : String, 20 | val begin_at : Long, 21 | val end_at : Long, 22 | val importance : Int, 23 | val count_down : Int 24 | ) 25 | 26 | data class Meta( 27 | val request_id : String, 28 | val trace_id : String 29 | ) 30 | -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/entity/ImageResult.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.entity 2 | 3 | import java.io.File 4 | 5 | @kotlinx.serialization.Serializable 6 | data class ImageResult( 7 | val id: Int = 0, 8 | val name: String = "", 9 | val path: String = "", 10 | val hash: String = "", 11 | val type: Int = 1, 12 | ) 13 | 14 | data class ImageRequestResult( 15 | val list: List = listOf(), 16 | val file: File? = null 17 | ) 18 | 19 | const val FuzzyImageResult = 0 -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/entity/ServerResponse.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.entity 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class ServerResponse( 7 | val status: Int, 8 | val message: String, 9 | val data: T 10 | ) 11 | -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/entity/TrainerOverride.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.entity 2 | 3 | /** 4 | * 保存trainer指令的覆盖信息 5 | * @author diyigemt 6 | * @since 1.0.9 7 | */ 8 | @kotlinx.serialization.Serializable 9 | data class TrainerOverride( 10 | val type: OverrideType, 11 | val name: String, 12 | val value: String 13 | ) { 14 | enum class OverrideType() { 15 | IMAGE, // 发送图片 16 | RAW, // 原生别名 17 | CODE // mirai-code 18 | } 19 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/entity/schaleDB/BaseDAO.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.entity.schaleDB 2 | 3 | /** 4 | *@Author hjn 5 | *@Create 2022/8/29 6 | */ 7 | interface BaseDAO { 8 | fun sendToDataBase() 9 | 10 | fun toModel(dao : T) : T 11 | 12 | fun getServer(type : Boolean) : String = if(type) "JPN" else "GLB" 13 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/event/BaseDatabaseInitEvent.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.event 2 | 3 | import net.mamoe.mirai.event.AbstractEvent 4 | 5 | /** 6 | * 当数据库初始化成功时发送 7 | */ 8 | class BaseDatabaseInitEvent: AbstractEvent() -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/event/ConfigInitSuccessEvent.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.event 2 | 3 | import net.mamoe.mirai.event.AbstractEvent 4 | 5 | /** 6 | * 当配置文件初始化成功时发送 7 | */ 8 | class ConfigInitSuccessEvent: AbstractEvent() -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/extension/CommandInterceptor.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.extension 2 | 3 | import net.mamoe.mirai.console.command.CommandSender 4 | import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors 5 | import net.mamoe.mirai.console.command.parse.CommandCall 6 | import net.mamoe.mirai.console.util.ConsoleExperimentalApi 7 | import net.mamoe.mirai.message.data.Message 8 | @OptIn(ExperimentalCommandDescriptors::class, ConsoleExperimentalApi::class) 9 | interface CommandInterceptor { 10 | val level: Int 11 | fun interceptCall(call: CommandCall): Boolean = true 12 | fun interceptBeforeCall(message: Message, caller: CommandSender): String? = null 13 | 14 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/extension/CommandInterceptorManager.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.extension 2 | 3 | import net.diyigemt.arona.interfaces.Initialize 4 | import net.diyigemt.arona.util.ReflectionUtil 5 | import net.mamoe.mirai.console.command.CommandSender 6 | import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors 7 | import net.mamoe.mirai.console.command.parse.CommandCall 8 | import net.mamoe.mirai.console.util.ConsoleExperimentalApi 9 | import net.mamoe.mirai.message.data.Message 10 | 11 | @OptIn(ExperimentalCommandDescriptors::class, ConsoleExperimentalApi::class) 12 | object CommandInterceptorManager: Initialize { 13 | private val ITEMS: MutableList = mutableListOf() 14 | fun registerItem(item: CommandInterceptor) { 15 | ITEMS.add(item) 16 | ITEMS.sortBy { it.level } 17 | } 18 | 19 | fun emitInterceptCall(call: CommandCall) { 20 | run loop@ { 21 | ITEMS.forEach { 22 | if (!it.interceptCall(call)) return@loop 23 | } 24 | } 25 | } 26 | 27 | fun emitInterceptBeforeCall(message: Message, caller: CommandSender): String? { 28 | ITEMS.forEach { 29 | val reason = it.interceptBeforeCall(message, caller) 30 | if (reason != null) return reason 31 | } 32 | return null 33 | } 34 | 35 | override fun init() { 36 | ReflectionUtil.getInterfacePetObjectInstance().forEach { 37 | registerItem(it) 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/extension/ExitCommandInterceptor.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.extension 2 | 3 | import net.diyigemt.arona.Arona 4 | import net.diyigemt.arona.util.NetworkUtil 5 | import net.diyigemt.arona.web.WebUIService 6 | import net.mamoe.mirai.console.command.CommandManager 7 | import net.mamoe.mirai.console.command.UserCommandSender 8 | import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors 9 | import net.mamoe.mirai.console.command.parse.CommandCall 10 | import net.mamoe.mirai.console.util.ConsoleExperimentalApi 11 | 12 | @OptIn(ExperimentalCommandDescriptors::class, ConsoleExperimentalApi::class) 13 | object ExitCommandInterceptor: CommandInterceptor { 14 | private val EXIT_COMMAND = listOf( 15 | "${CommandManager.commandPrefix}stop", 16 | "${CommandManager.commandPrefix}shutdown", 17 | "${CommandManager.commandPrefix}exit" 18 | ) 19 | override val level: Int = 1 20 | 21 | override fun interceptCall(call: CommandCall): Boolean { 22 | if (call.caller is UserCommandSender) return true 23 | val calleeName = call.calleeName 24 | val valueArguments = call.valueArguments 25 | if (valueArguments.isEmpty() && EXIT_COMMAND.contains(calleeName)) { 26 | Arona.sendExitMessage() 27 | NetworkUtil.logoutInstance() 28 | WebUIService.disableService() 29 | } 30 | return true 31 | } 32 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/interfaces/CoroutineFunctionProvider.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.interfaces 2 | 3 | import kotlinx.coroutines.* 4 | import net.diyigemt.arona.Arona 5 | 6 | abstract class CoroutineFunctionProvider { 7 | 8 | abstract val tag: String 9 | 10 | protected abstract suspend fun main() 11 | 12 | @Suppress("NOTHING_TO_INLINE") 13 | inline fun warning(text: String) { 14 | Arona.warning { "$tag: $text" } 15 | } 16 | @Suppress("NOTHING_TO_INLINE") 17 | inline fun error(text: String) { 18 | Arona.error { "$tag: $text" } 19 | } 20 | @Suppress("NOTHING_TO_INLINE") 21 | inline fun info(text: String) { 22 | Arona.info { "$tag: $text" } 23 | } 24 | @Suppress("NOTHING_TO_INLINE") 25 | inline fun verbose(text: String) { 26 | Arona.verbose { "$tag: $text" } 27 | } 28 | 29 | fun start() : Job = Arona.runSuspend { main() } 30 | 31 | open fun disable() {} 32 | 33 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/interfaces/Initialize.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.interfaces 2 | 3 | interface Initialize { 4 | 5 | /** 6 | * 初始化方法调用优先级, 数字越小优先级越高 7 | * 100: 保留 8 | * 11-99: 非核心功能 9 | * 1-10: 核心功能 10 | * 0: 保留 11 | */ 12 | val priority: Int 13 | get() = 100 14 | 15 | fun init() 16 | 17 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/remote/RemoteService.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.remote 2 | 3 | import kotlin.reflect.KType 4 | 5 | interface RemoteService { 6 | 7 | val kType: KType 8 | val type: RemoteServiceAction 9 | fun handleService(data: T, time: String, aid: Long) 10 | 11 | } 12 | 13 | enum class RemoteServiceAction( 14 | val action: String 15 | ) { 16 | ANNOUNCEMENT("announcement"), // 公告消息 17 | POOL_UPDATE("poolUpdate"), // 卡池更新消息 18 | VERSION_UPDATE("versionUpdate"), // 版本更新消息 19 | NULL("null"); 20 | companion object { 21 | fun getRemoteServiceActionByName(name: String): RemoteServiceAction = 22 | RemoteServiceAction.values() 23 | .firstOrNull { it.action == name } 24 | ?: NULL 25 | } 26 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/remote/action/AnnouncementRemoteService.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.remote.action 2 | 3 | import net.diyigemt.arona.Arona 4 | import net.diyigemt.arona.remote.RemoteService 5 | import net.diyigemt.arona.remote.RemoteServiceAction 6 | import kotlin.reflect.KType 7 | import kotlin.reflect.full.createType 8 | 9 | object AnnouncementRemoteService : RemoteService { 10 | // override val kType: KType = List::class.createType(listOf(KTypeProjection.invariant(AnnouncementItem::class.starProjectedType))) 11 | override val kType: KType = String::class.createType() 12 | override val type: RemoteServiceAction = RemoteServiceAction.ANNOUNCEMENT 13 | 14 | override fun handleService(data: String, time: String, aid: Long) { 15 | Arona.sendMessageToAdmin("新公告(${time}):\n${data}") 16 | } 17 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/service/AronaGroupService.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.service 2 | 3 | interface AronaGroupService: AronaService -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/service/AronaManageService.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.service 2 | 3 | import net.diyigemt.arona.Arona 4 | import net.diyigemt.arona.config.GlobalConfigProvider 5 | import net.mamoe.mirai.contact.Contact 6 | import net.mamoe.mirai.contact.User 7 | import net.mamoe.mirai.message.code.MiraiCode 8 | 9 | interface AronaManageService: AronaService { 10 | 11 | fun checkAdmin(user: User, contact: Contact): Boolean { 12 | val managerGroup = GlobalConfigProvider.get>("managerGroup") 13 | if (!managerGroup.contains(user.id)) { 14 | val permissionDeniedMessage = GlobalConfigProvider.getGroup("permissionDeniedMessage", contact.id) 15 | if (permissionDeniedMessage != "") { 16 | Arona.runSuspend { 17 | contact.sendMessage(MiraiCode.deserializeMiraiCode(permissionDeniedMessage, contact)) 18 | } 19 | } 20 | return false 21 | } 22 | return true 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/service/AronaMessageReactService.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.service 2 | 3 | import net.mamoe.mirai.event.events.MessageEvent 4 | 5 | interface AronaMessageReactService: AronaReactService { 6 | 7 | override fun checkService(event: T): Boolean { 8 | return true 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/service/AronaQuartzService.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.service 2 | 3 | import net.diyigemt.arona.quartz.QuartzProvider 4 | import org.quartz.JobKey 5 | 6 | interface AronaQuartzService: AronaService { 7 | var jobKey: JobKey? 8 | 9 | override fun disableService() { 10 | if (jobKey != null) { 11 | QuartzProvider.deleteTask(jobKey!!) 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/service/AronaReactService.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.service 2 | 3 | import net.mamoe.mirai.event.events.BotEvent 4 | import kotlin.reflect.KClass 5 | 6 | interface AronaReactService: AronaService { 7 | 8 | val event: KClass 9 | 10 | fun checkService(event: T): Boolean 11 | 12 | suspend fun handle(event: T) 13 | 14 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/service/AronaService.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.service 2 | 3 | interface AronaService { 4 | /** 5 | * 服务的唯一id 6 | */ 7 | val id: Int 8 | 9 | /** 10 | * 服务的名称,用于在可交互式配置中给用户标识服务? 11 | */ 12 | val name: String 13 | 14 | /** 15 | * 服务描述? 既然这样name还有用吗? 16 | */ 17 | val description: String 18 | 19 | /** 20 | * 是否为全集单例(不允许群单独设置开关/忽略单独设置的值) 21 | */ 22 | val isGlobal: Boolean 23 | get() = false 24 | 25 | // remind to registerService 26 | fun registerService() { 27 | AronaServiceManager.register(this) 28 | } 29 | fun enableService() {} 30 | fun disableService() {} 31 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/util/MoshiUtil.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.util 2 | 3 | import com.squareup.moshi.Moshi 4 | import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory 5 | 6 | /** 7 | *@Author hjn 8 | *@Create 2022/10/22 9 | */ 10 | object MoshiUtil { 11 | val reflect: Moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build() 12 | 13 | val builtIn: Moshi = Moshi.Builder().build() 14 | 15 | fun custom(adapter: Any): Moshi = Moshi.Builder().add(adapter).addLast(KotlinJsonAdapterFactory()).build() 16 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/util/TimeUtil.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.util 2 | 3 | import java.util.* 4 | import kotlin.math.floor 5 | 6 | object TimeUtil { 7 | 8 | fun today(): Int = Calendar.getInstance().get(Calendar.DAY_OF_MONTH) 9 | 10 | fun calcTime(now: Date, time: Date, future: Boolean = false): String { 11 | val hour = floor(((time.time - now.time) / 1000 / 60 / 60).toDouble()) 12 | val day = floor(hour / 24).toInt() 13 | val leftHour = (hour - day * 24).toInt() 14 | return "${day}天${leftHour}小时后" + if (future) "开始" else "结束" 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/util/scbaleDB/factories/BaseFactory.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.util.scbaleDB.factories 2 | 3 | /** 4 | *@Author hjn 5 | *@Create 2022/8/20 6 | */ 7 | abstract class BaseFactory { 8 | fun getValueById(id : Int) : String?{ 9 | for (member in this::class.members){ 10 | if (member.name == id.toString()) return member.call(this).toString() 11 | } 12 | 13 | return null 14 | } 15 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/util/scbaleDB/factories/CalendarFactory.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.util.scbaleDB.factories 2 | 3 | import net.diyigemt.arona.entity.schaleDB.LocalizationDAO 4 | import net.diyigemt.arona.entity.schaleDB.Raid 5 | import net.diyigemt.arona.entity.schaleDB.RaidDAO 6 | import net.diyigemt.arona.entity.schaleDB.StudentDAO 7 | import net.diyigemt.arona.util.scbaleDB.SchaleDBUtil 8 | 9 | /** 10 | *@Author hjn 11 | *@Create 2022/8/20 12 | */ 13 | object CalendarFactory { 14 | fun getEventLocalizationName(eventID : Int) : String{ 15 | val localizationData: LocalizationDAO = SchaleDBUtil.localizationItem 16 | val res = localizationData.EventName[eventID.toString()] 17 | 18 | return res ?: "" 19 | } 20 | 21 | fun getCharacterLocalizationName(characterIDList : List) : String{ 22 | val studentData: StudentDAO = SchaleDBUtil.studentItem 23 | var res = "" 24 | for (item in characterIDList){ 25 | res += studentData.getStudentNameById(item) + " " 26 | } 27 | 28 | return res 29 | } 30 | 31 | fun getRaidLocalizationName(raidID : Int) : String { 32 | val raidData: RaidDAO = SchaleDBUtil.raidItem 33 | val res = raidData.getRaidNameById(raidID) 34 | 35 | return res ?: "" 36 | } 37 | 38 | fun getRaidById(raidID: Int) : Raid?{ 39 | for (item in SchaleDBUtil.raidItem.Raid){ 40 | if (raidID == item.Id) return item 41 | } 42 | 43 | return null 44 | } 45 | 46 | fun getRaidStatus(raidID: Int) : Boolean = SchaleDBUtil.raidItem.isRaidReleased(raidID) 47 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/util/sys/SysStatic.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.util.sys 2 | 3 | /** 4 | * @description 所有可用的key保存位置 5 | * @author diyigemt 6 | * @date 2022/9/19 16:19 7 | */ 8 | enum class SysStatic(val key: String) { 9 | UUID("uuid"), 10 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/web/LoginService.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.web 2 | 3 | import com.auth0.jwt.JWT 4 | import com.auth0.jwt.algorithms.Algorithm 5 | import net.diyigemt.arona.Arona 6 | import net.diyigemt.arona.service.AronaManageService 7 | import net.diyigemt.arona.service.AronaService 8 | import net.mamoe.mirai.console.command.SimpleCommand 9 | import net.mamoe.mirai.console.command.UserCommandSender 10 | import java.util.* 11 | 12 | /** 13 | *@Author hjn 14 | *@Create 2022/11/8 15 | */ 16 | object LoginService { 17 | //以下两个变量初始化需要保证ktor先被初始化 18 | // lateinit var jwtAudience: String 19 | // lateinit var issuer: String 20 | // lateinit var secret: String 21 | 22 | // @Handler 23 | // fun handler(){ 24 | // val res = JWT.create() 25 | // .withAudience(jwtAudience) 26 | // .withIssuer(issuer) 27 | // .withExpiresAt(Date(System.currentTimeMillis() + 60000)) 28 | // .sign(Algorithm.HMAC256(secret)) 29 | // 30 | // Arona.info(res) 31 | // } 32 | 33 | // override val id: Int = 25 34 | // override val name: String = "密钥" 35 | // override var enable: Boolean = true 36 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/web/api/v1/Worker.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.web.api.v1 2 | 3 | import io.ktor.http.* 4 | import io.ktor.server.application.* 5 | import io.ktor.server.response.* 6 | import io.ktor.util.pipeline.* 7 | import kotlinx.serialization.encodeToString 8 | import kotlinx.serialization.json.Json 9 | import net.diyigemt.arona.web.api.v1.message.ServerResponse 10 | 11 | /** 12 | *@Author hjn 13 | *@Create 2022/10/16 14 | */ 15 | interface Worker { 16 | suspend fun worker(context : PipelineContext){ 17 | context.call.response.header("Content-Type", "application/json") 18 | } 19 | 20 | val json: Json 21 | get() = Json { encodeDefaults = true } 22 | 23 | fun fail() = json.encodeToString(ServerResponse(500, HttpStatusCode.InternalServerError.description, null as String?)) 24 | 25 | fun noContent() = json.encodeToString(ServerResponse(204, HttpStatusCode.NoContent.description, null as String?)) 26 | } 27 | 28 | inline fun responseMessage(json: T, code: Int = 200) = Json.encodeToString( 29 | ServerResponse(code, HttpStatusCode.OK.description, json) 30 | ) -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/web/api/v1/config/ConfigService.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.web.api.v1.config 2 | 3 | import io.ktor.http.* 4 | import io.ktor.server.application.* 5 | import io.ktor.server.response.* 6 | import io.ktor.util.pipeline.* 7 | import kotlinx.serialization.Serializable 8 | import net.diyigemt.arona.config.GlobalConfigProvider 9 | import net.diyigemt.arona.entity.BotGroupConfig 10 | import net.diyigemt.arona.web.api.v1.Worker 11 | import net.diyigemt.arona.web.api.v1.message.ServerResponse 12 | 13 | /** 14 | *@Author hjn 15 | *@Create 2022/10/17 16 | */ 17 | object ConfigService : Worker{ 18 | override suspend fun worker(context: PipelineContext) { 19 | super.worker(context) 20 | kotlin.runCatching { 21 | context.call.respond(ServerResponse(200, "OK", Configs())) 22 | }.onFailure { 23 | it.printStackTrace() 24 | context.call.respond(ServerResponse(500, HttpStatusCode.InternalServerError.description, "")) 25 | } 26 | } 27 | 28 | @Serializable 29 | data class Configs( 30 | val bots: List = GlobalConfigProvider.getBotConfig(), 31 | val managerGroup: List = GlobalConfigProvider.getGroupList(), 32 | ) 33 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/web/api/v1/message/ContentUnit.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.web.api.v1.message 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | /** 6 | *@Author hjn 7 | *@Create 2022/10/17 8 | */ 9 | @Serializable 10 | data class ContentUnit( 11 | val value : T, 12 | val description : String 13 | ) -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/web/api/v1/message/DBJob.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.web.api.v1.message 2 | 3 | 4 | /** 5 | *@Author hjn 6 | *@Create 2022/10/22 7 | */ 8 | data class DBJob( 9 | val jobName: String? = null, 10 | val description: String? = null, 11 | val properties: Properties 12 | ) 13 | 14 | 15 | data class Properties( 16 | var db: String = "", 17 | var table: String = "", 18 | val task: Task 19 | ) 20 | 21 | 22 | data class Task( 23 | val strategy: String, 24 | val args: Map? = null, 25 | val where: Map? = null 26 | ) -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/web/api/v1/message/ServerResponse.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.web.api.v1.message 2 | 3 | import com.squareup.moshi.JsonClass 4 | import kotlinx.serialization.Serializable 5 | 6 | /** 7 | *@Author hjn 8 | *@Create 2022/10/16 9 | */ 10 | 11 | @Serializable 12 | @JsonClass(generateAdapter = true) 13 | data class ServerResponse( 14 | val code : Int, 15 | val message : String, 16 | val data : T? = null 17 | ) -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/web/api/v1/mirai/BotsAPI.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.web.api.v1.mirai 2 | 3 | import io.ktor.http.* 4 | import io.ktor.server.application.* 5 | import io.ktor.server.response.* 6 | import io.ktor.util.pipeline.* 7 | import net.diyigemt.arona.config.GlobalConfigProvider 8 | import net.diyigemt.arona.web.api.v1.Worker 9 | import net.diyigemt.arona.web.api.v1.message.ServerResponse 10 | import net.diyigemt.arona.web.api.v1.responseMessage 11 | import net.diyigemt.arona.web.entity.BotFriend 12 | import net.mamoe.mirai.Bot 13 | import net.mamoe.mirai.contact.nameCardOrNick 14 | 15 | /** 16 | *@Author hjn 17 | *@Create 2023/2/23 18 | */ 19 | object BotsAPI: Worker { 20 | override suspend fun worker(context: PipelineContext) { 21 | super.worker(context) 22 | kotlin.runCatching { 23 | val res: MutableList = mutableListOf() 24 | GlobalConfigProvider.getBotConfig().map { it.bot }.forEach { 25 | Bot.getInstanceOrNull(it).apply { 26 | if (this != null) res.add(BotFriend(it, this.nameCardOrNick, "")) 27 | } 28 | } 29 | return@runCatching res 30 | }.onFailure { 31 | it.printStackTrace() 32 | context.call.respond(ServerResponse(500, HttpStatusCode.InternalServerError.description, "")) 33 | }.onSuccess { context.call.respond(responseMessage(it)) } 34 | } 35 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/web/database/Strategy.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.web.database 2 | 3 | /** 4 | *@Author hjn 5 | *@Create 2022/10/22 6 | */ 7 | enum class Strategy { 8 | INSERT, DELETE, UPDATE, SELECT 9 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/web/database/security/OptionFilter.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.web.database.security 2 | 3 | import io.ktor.http.* 4 | import net.diyigemt.arona.web.api.v1.message.DBJob 5 | import net.diyigemt.arona.web.api.v1.message.ServerResponse 6 | import net.diyigemt.arona.web.database.Strategy 7 | 8 | /** 9 | *@Author hjn 10 | *@Create 2022/10/22 11 | */ 12 | object OptionFilter { 13 | /** 14 | * 将你希望对某个表只执行固定操作的数据库操作加入*/ 15 | private val tables : MutableMap> = mutableMapOf( 16 | Pair("GachaHistory", listOf(Strategy.SELECT, Strategy.DELETE)), 17 | Pair("GachaLimit", listOf(Strategy.SELECT, Strategy.DELETE)) 18 | ) 19 | fun optionCheck(job : DBJob) : ServerResponse = when{ 20 | (tables[job.properties.table] != null && 21 | !tables[job.properties.table]!!.contains(Strategy.valueOf(job.properties.task.strategy.uppercase()))) -> { 22 | ServerResponse(HttpStatusCode.MethodNotAllowed.value, "Strategy Not Allowed", null as String?) 23 | } 24 | 25 | else ->{ServerResponse(HttpStatusCode.OK.value, HttpStatusCode.OK.description)} 26 | } 27 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/web/entity/BotContact.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.web.entity 2 | 3 | import kotlinx.serialization.Serializable 4 | import net.mamoe.mirai.contact.* 5 | 6 | /** 7 | * bot和它的联系人们 8 | */ 9 | @Serializable 10 | data class BotContact( 11 | val bot: Long, 12 | val friends: List, 13 | val groups: List 14 | ) 15 | 16 | @Serializable 17 | data class BotGroup ( 18 | val id : Long, 19 | val name : String, 20 | val permission: MemberPermission 21 | ) 22 | 23 | @Serializable 24 | data class BotFriend ( 25 | val id : Long, 26 | val name : String, 27 | val remark: String 28 | ) 29 | 30 | @Serializable 31 | data class BotGroupMember ( 32 | val id : Long, 33 | val memberName : String, 34 | val permission: MemberPermission, 35 | val specialTitle: String, 36 | val joinTimestamp: Int, 37 | val lastSpeakTimestamp: Int, 38 | val muteTimeRemaining: Int, 39 | val group: BotGroup, 40 | ) 41 | 42 | fun Group.toGroup(): BotGroup = BotGroup(this.id, this.name, this.botPermission) 43 | fun Friend.toFriend(): BotFriend = BotFriend(this.id, this.nameCardOrNick, this.remarkOrNick) 44 | fun NormalMember.toMember(): BotGroupMember = BotGroupMember( 45 | this.id, 46 | this.nameCardOrNick, 47 | this.permission, 48 | this.specialTitle, 49 | this.joinTimestamp, 50 | this.lastSpeakTimestamp, 51 | this.muteTimeRemaining, 52 | BotGroup(this.group.id, this.group.name, this.group.botPermission) 53 | ) -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/web/plugins/Cros.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.web.plugins 2 | 3 | import io.ktor.http.* 4 | import io.ktor.server.application.* 5 | import io.ktor.server.plugins.cors.routing.* 6 | 7 | fun Application.configureCROS(){ 8 | install(CORS) { 9 | allowMethod(HttpMethod.Options) 10 | allowMethod(HttpMethod.Put) 11 | allowMethod(HttpMethod.Delete) 12 | allowMethod(HttpMethod.Patch) 13 | allowHeader(HttpHeaders.Authorization) 14 | allowHeader(HttpHeaders.Accept) 15 | allowHeader(HttpHeaders.AcceptEncoding) 16 | allowHeader(HttpHeaders.AcceptLanguage) 17 | allowHeader(HttpHeaders.ContentType) 18 | allowHeader(HttpHeaders.Cookie) 19 | allowHeader(HttpHeaders.AccessControlAllowHeaders) 20 | allowHeader(HttpHeaders.AccessControlAllowCredentials) 21 | allowHeader(HttpHeaders.AccessControlRequestMethod) 22 | allowHeader(HttpHeaders.AccessControlAllowOrigin) 23 | allowHeader(HttpHeaders.CacheControl) 24 | allowHeader(HttpHeaders.Connection) 25 | allowHeader(HttpHeaders.Host) 26 | allowHeader(HttpHeaders.Origin) 27 | allowHeader(HttpHeaders.Pragma) 28 | allowHeader(HttpHeaders.Referrer) 29 | allowHeader("Sec-Fetch-Dest") 30 | allowHeader("Sec-Fetch-Mode") 31 | allowHeader("Sec-Fetch-Site") 32 | allowHeader("arona-file-name") 33 | allowHeader(HttpHeaders.UserAgent) 34 | anyHost() // @TODO: Don't do this in production if possible. Try to limit it. 35 | } 36 | } -------------------------------------------------------------------------------- /arona-core/src/main/kotlin/net/diyigemt/arona/web/plugins/Routing.kt: -------------------------------------------------------------------------------- 1 | package net.diyigemt.arona.web.plugins 2 | 3 | import io.ktor.server.application.* 4 | import io.ktor.server.http.content.* 5 | import io.ktor.server.routing.* 6 | import net.diyigemt.arona.Arona 7 | 8 | fun Application.configureRouting() { 9 | routing { 10 | static("/") { 11 | file("/", "${Arona.dataFolder.absolutePath}/dist/index.html") 12 | } 13 | 14 | // Static plugin. Try to access `/static/index.css` 15 | static("/static") { 16 | files("${Arona.dataFolder.absolutePath}/dist/static") 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /arona-core/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory: -------------------------------------------------------------------------------- 1 | org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory -------------------------------------------------------------------------------- /arona-core/src/main/resources/META-INF/services/net.mamoe.mirai.console.plugin.jvm.JvmPlugin: -------------------------------------------------------------------------------- 1 | net.diyigemt.arona.Arona -------------------------------------------------------------------------------- /arona-core/src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "net.diyigemt.arona" 2 | version: "2.0.0-M1" 3 | name: "ba-activity-pusher" 4 | author: "diyigemt" 5 | info: "BA日服/国际服活动推送插件" -------------------------------------------------------------------------------- /arona-core/src/test/kotlin/RunMirai.kt: -------------------------------------------------------------------------------- 1 | package org.example.mirai.plugin 2 | 3 | import net.diyigemt.arona.Arona 4 | import net.mamoe.mirai.alsoLogin 5 | import net.mamoe.mirai.console.MiraiConsole 6 | import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.enable 7 | import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.load 8 | import net.mamoe.mirai.console.terminal.MiraiConsoleTerminalLoader 9 | import net.mamoe.mirai.console.util.ConsoleExperimentalApi 10 | import java.io.File 11 | import java.util.* 12 | 13 | @OptIn(ConsoleExperimentalApi::class) 14 | suspend fun main() { 15 | MiraiConsoleTerminalLoader.startAsDaemon() 16 | 17 | val pluginInstance = Arona 18 | 19 | pluginInstance.load() // 主动加载插件, Console 会调用 Dice.onLoad 20 | pluginInstance.enable() // 主动启用插件, Console 会调用 Dice.onEnable 21 | 22 | // val properties = Properties().apply { File("account.properties").inputStream().use { load(it) } } 23 | // 24 | // val bot = MiraiConsole.addBot(properties.getProperty("id").toLong(), properties.getProperty("password")) 25 | // .alsoLogin() // 登录一个测试环境的 Bot 26 | 27 | MiraiConsole.job.join() 28 | } -------------------------------------------------------------------------------- /arona-core/src/test/kotlin/TestGenericJson.kt: -------------------------------------------------------------------------------- 1 | package org.example.mirai.plugin 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.json.Json 5 | import kotlinx.serialization.serializer 6 | import org.junit.jupiter.api.Test 7 | import kotlin.reflect.full.createType 8 | 9 | /** 10 | * @description 11 | * @author diyigemt 12 | * @date 2022/9/27 12:11 13 | */ 14 | class TestGenericJson { 15 | 16 | @Serializable 17 | data class TestData( 18 | val name: String 19 | ) 20 | 21 | @Test 22 | fun testJsonParse() { 23 | val se = serializer(TestData::class.createType()) 24 | val td = Json.decodeFromString(se, "{\"name\":\"hahaha\"}") 25 | println((td as TestData).name) 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /arona-doc/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] # 表示所有文件都要遵循 7 | indent_style = space # 缩进风格,可选配置有space和tab 8 | indent_size = 2 # 缩进大小 9 | end_of_line = lf # 换行符,可选配置有lf、cr和crlf 10 | charset = utf-8 # 编码格式,通常都是选utf-8 11 | trim_trailing_whitespace = true # 去除多余的空格 12 | insert_final_newline = true # 在尾部插入一行 13 | 14 | [*.md] # 表示仅 md 文件适用 15 | insert_final_newline = false # 在尾部插入一行 16 | trim_trailing_whitespace = false # 去除多余的空格 17 | -------------------------------------------------------------------------------- /arona-doc/.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | 7 | # Declare files that will always have CRLF line endings on checkout. 8 | *.vue text eol=lf 9 | *.ts text eol=lf 10 | *.js text eol=lf 11 | *.scss text eol=lf 12 | 13 | # Denote all files that are truly binary and should not be modified. 14 | *.png binary 15 | *.jpg binary 16 | *.webp binary 17 | *.svg binary 18 | *.woff binary 19 | *.woff2 binary 20 | *.yaml binary 21 | *.json binary 22 | *.json binary 23 | -------------------------------------------------------------------------------- /arona-doc/.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /docs/.vitepress/cache/ 3 | /docs/.vitepress/dist/ 4 | /node_modules/ 5 | .DS_Store 6 | /test/ 7 | /docs/.vitepress/*.7z -------------------------------------------------------------------------------- /arona-doc/.prettierignore: -------------------------------------------------------------------------------- 1 | /docs/.vitepress/cache/ 2 | /docs/.vitepress/dist/ 3 | /docs/docs/ 4 | -------------------------------------------------------------------------------- /arona-doc/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": false, 3 | "endOfLine": "lf", 4 | "arrowParens": "avoid", 5 | "trailingComma": "es5", 6 | "useTabs": false, 7 | "semi": true 8 | } 9 | -------------------------------------------------------------------------------- /arona-doc/README.md: -------------------------------------------------------------------------------- 1 | # arona的doc 2 | -------------------------------------------------------------------------------- /arona-doc/components.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* prettier-ignore */ 3 | // @ts-nocheck 4 | // Generated by unplugin-vue-components 5 | // Read more: https://github.com/vuejs/core/pull/3399 6 | import '@vue/runtime-core' 7 | 8 | export {} 9 | 10 | declare module '@vue/runtime-core' { 11 | export interface GlobalComponents { 12 | RouterLink: typeof import('vue-router')['RouterLink'] 13 | RouterView: typeof import('vue-router')['RouterView'] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /arona-doc/docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | import Theme from 'vitepress/theme'; 2 | import './custom_style.scss'; 3 | import 'element-plus/theme-chalk/dark/css-vars.css'; 4 | import { h } from 'vue'; 5 | 6 | // @ts-ignore 7 | import RegisterSW from './components/RegisterSW.vue'; 8 | 9 | export default { 10 | ...Theme, 11 | Layout() { 12 | try { 13 | // @ts-ignore 14 | if ('development' === import.meta.env.MODE) { 15 | return h(Theme.Layout); 16 | } 17 | } catch (e) { 18 | console.log(e); 19 | } 20 | return h(Theme.Layout, null, { 21 | 'layout-bottom': () => h(RegisterSW), 22 | }); 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /arona-doc/docs/api/announcement.md: -------------------------------------------------------------------------------- 1 | # 最后的公告 2 | 3 | 实际上也算不上最后了,大家也已经看到了,2.0.0-dev这个分支挂在这也大半年了, 由于转职成社畜以后空余时间急剧减少,本项目的开发实质上已经停止,加之tx最近对bot打压力度的加大,在找到国服稳定的活动信源后仓库维护将彻底停止,进入archive状态。 4 | 5 | 当然学生/活动数据会一直更新,这点请大家放心,毕竟我还没退游呢。 6 | 7 | ~~所以没有跑路,歇会而已。~~ 8 | 9 | api也已经公开,希望能帮助到现存的以及后来的ba bot开发者。 10 | 11 | [bot攻略数据公开计划](https://doc.arona.diyigemt.com/api/) 12 | 13 | 最后,感谢各位这一年来的支持,我们下个项目再见。 14 | 15 | 不到一周下个项目就来了,基于bot数据的简略速查网站[AronaBot](https://tutorial.arona.diyigemt.com/home) -------------------------------------------------------------------------------- /arona-doc/docs/auto-imports.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* prettier-ignore */ 3 | // @ts-nocheck 4 | // Generated by unplugin-auto-import 5 | export {} 6 | declare global {} 7 | -------------------------------------------------------------------------------- /arona-doc/docs/command/auto.md: -------------------------------------------------------------------------------- 1 | # 非主动触发 2 | 3 | ## 复读 4 | 5 | 当群里不同的人发送同一条消息超过`arona-repeat.yml->times`的配置时,机器人自己复读一条相同的消息 6 | 7 | ## 戳一戳回复 8 | 9 | 当戳一戳arona时根据`arona-nudge.yml`的配置随机回复一条消息 10 | 11 | ::: details 效果 12 | 13 | nudge 14 | 15 | ::: 16 | 17 | ## 发情回复 18 | 19 | 当发送的内容中包含 "老公"/"老婆"文字时根据`arona-hentai.yml`的配置随机回复一条消息 20 | 21 | ## 活动防侠推送 22 | 23 | 当活动还有1小时结束,或者在指定的配置时间时发送活动即将结束消息 24 | 25 | ## NGA图楼推送 26 | 27 | 当NGA图楼更新时将图转发到群中 28 | 29 | ## 更新检查 30 | 31 | 每日版本更新发现新版本时将更新消息通过私聊发 送到具有管理员权限的qq中 32 | -------------------------------------------------------------------------------- /arona-doc/docs/command/remote.md: -------------------------------------------------------------------------------- 1 | # 远端服务 2 | 3 | ::: info 4 | 5 | 所有的远端服务均为作者手动维护,如果遇到信息更新延迟的情况说明作者懒狗了,请谅解。 6 | 7 | ::: 8 | 9 | ## 攻略指令 10 | 11 | `/攻略`指令提供的所有地图、学生以及杂图图片全部保存在远端,在执行攻`/攻略`令时,arona将会查询本地文件夹下是否有对应的图片,若没有将会从远端进行下载。 12 | 13 | 同时,arona也会检查本地保存的图片与远端图片的md5校验值,若不一致将会重新下载。 14 | 15 | 以上两个过程,实现了攻略图片自动更新的功能。 16 | 17 | ## 公告 18 | 19 | arona将会根据`arona.yml`配置文件中的`remoteCheckInterval`配置项定期向远端查询新的公告信息,下面是一个示例: 20 | 21 | ::: details 公告示例 22 | 23 | announcment 24 | 25 | ::: 26 | 27 | 基本上是用来通知攻略图片的更新信息的。 28 | 29 | ## 卡池自动更新 30 | 31 | arona将会根据`arona.yml`配置文件中的`remoteCheckInterval`配置项定期向远端查询新的卡池,下面是一个示例: 32 | 33 | ::: details 卡池更新示例 34 | 35 | pool-update 36 | 37 | ::: 38 | 39 | 设置成手动更新的原因是怕用户自己已经有这个池子了。 40 | -------------------------------------------------------------------------------- /arona-doc/docs/components.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* prettier-ignore */ 3 | // @ts-nocheck 4 | // Generated by unplugin-vue-components 5 | // Read more: https://github.com/vuejs/core/pull/3399 6 | import '@vue/runtime-core' 7 | 8 | export {}; 9 | 10 | declare module '@vue/runtime-core' { 11 | export interface GlobalComponents { 12 | ElButton: typeof import('element-plus/es')['ElButton']; 13 | ElCard: typeof import('element-plus/es')['ElCard']; 14 | ElCheckbox: typeof import('element-plus/es')['ElCheckbox']; 15 | ElDatePicker: typeof import('element-plus/es')['ElDatePicker']; 16 | ElDivider: typeof import('element-plus/es')['ElDivider']; 17 | ElIcon: typeof import('element-plus/es')['ElIcon']; 18 | ElInput: typeof import('element-plus/es')['ElInput']; 19 | ElOption: typeof import('element-plus/es')['ElOption']; 20 | ElSelect: typeof import('element-plus/es')['ElSelect']; 21 | ElSelectV2: typeof import('element-plus/es')['ElSelectV2']; 22 | ElSpace: typeof import('element-plus/es')['ElSpace']; 23 | RouterLink: typeof import('vue-router')['RouterLink']; 24 | RouterView: typeof import('vue-router')['RouterView']; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /arona-doc/docs/docs/auto-imports.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* prettier-ignore */ 3 | // @ts-nocheck 4 | // Generated by unplugin-auto-import 5 | export {} 6 | declare global { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /arona-doc/docs/docs/components.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* prettier-ignore */ 3 | // @ts-nocheck 4 | // Generated by unplugin-vue-components 5 | // Read more: https://github.com/vuejs/core/pull/3399 6 | import '@vue/runtime-core' 7 | 8 | export {} 9 | 10 | declare module '@vue/runtime-core' { 11 | export interface GlobalComponents { 12 | ElButton: typeof import('element-plus/es')['ElButton'] 13 | ElCard: typeof import('element-plus/es')['ElCard'] 14 | ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] 15 | ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] 16 | ElDivider: typeof import('element-plus/es')['ElDivider'] 17 | ElIcon: typeof import('element-plus/es')['ElIcon'] 18 | ElInput: typeof import('element-plus/es')['ElInput'] 19 | ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] 20 | ElOption: typeof import('element-plus/es')['ElOption'] 21 | ElSelect: typeof import('element-plus/es')['ElSelect'] 22 | ElSpace: typeof import('element-plus/es')['ElSpace'] 23 | RouterLink: typeof import('vue-router')['RouterLink'] 24 | RouterView: typeof import('vue-router')['RouterView'] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /arona-doc/docs/guide/glossary.md: -------------------------------------------------------------------------------- 1 | # 词汇表 2 | 3 | ## bot 4 | 5 | 特指qq机器人,所谓qq机器人,就是用代码去控制一个真实的qq账号来主动发送或者被动回应接到的消息,所以你需要一个空闲的、真实存在的,能够正常登录qq号来运行机器人 6 | 7 | ## mirai 8 | 9 | [mirai](https://github.com/mamoe/mirai/) 是一个在全平台下运行,提供 QQ Android 协议支持的高效率机器人库 10 | 11 | ## mirai-console 12 | 13 | [mirai-console](https://github.com/mamoe/mirai/tree/dev/mirai-console) 是基于[mirai](#mirai)的高效率机器人框架 14 | 15 | ## mirai-console-loader 16 | 17 | [mirai-console-loader](https://github.com/iTXTech/mirai-console-loader) 简称mcl, 是一个模块化、轻量级且支持完全自定义的基于[mirai-console](#mirai-console)的[mirai](#mirai)加载器 18 | 19 | 安装过程中所有步骤都基于mcl进行 20 | 21 | ## console 22 | 23 | 指[mirai-console](#mirai-console)运行后的交互界面 24 | 25 | ## arona 26 | 27 | 指本插件 超级草莓牛奶arona 28 | -------------------------------------------------------------------------------- /arona-doc/docs/guide/what-is.md: -------------------------------------------------------------------------------- 1 | # 她能干啥 2 | 3 | arona是基于mirai-console的qq机器人插件。 4 | 5 | 作为BA(Blue Archive)的一款群助手,她可以实现以下功能: 6 | 7 | ::: details 活动日历 8 | 9 | calendar 10 | 11 | ::: 12 | 13 | ::: details 活动结束前防侠 14 | 15 | notify 16 | 17 | ::: 18 | 19 | ::: details 抽卡模拟 20 | 21 | gacha 22 | 23 | ::: 24 | 25 | ::: details 主线地图图文攻略 26 | 27 | chapter-map 28 | 29 | ::: 30 | 31 | ::: details 学生攻略(主图来源猫佬) 32 | 33 | student 34 | 35 | ::: 36 | 37 | ::: details 活动攻略等 38 | 39 | active-info 40 | 41 | ::: 42 | 43 | ::: details 塔罗牌 44 | 45 | tarot 46 | 47 | ::: 48 | 49 | ::: details nga图楼推送 50 | 51 | nga 52 | 53 | ::: 54 | 55 | ::: details 更新检查 56 | 57 | update 58 | 59 | ::: 60 | 61 | ::: details 不停机管理 62 | 63 | manage-1 64 | 65 | manage-2 66 | 67 | ::: 68 | -------------------------------------------------------------------------------- /arona-doc/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | 4 | title: Arona 配置手册 5 | titleTemplate: シッテムの箱 6 | 7 | hero: 8 | name: Arona 配置手册 9 | text: "" 10 | tagline: '"是常驻这个「シッテムの箱」的系统管理员和主操作系统, 也是今后协助老师的秘书!"' 11 | image: 12 | src: /logo.webp 13 | alt: VitePress 14 | actions: 15 | - theme: brand 16 | text: Get Started 17 | link: /guide/what-is 18 | - theme: alt 19 | text: View on Github 20 | link: https://github.com/diyigemt/arona 21 | --- 22 | 23 | 34 | -------------------------------------------------------------------------------- /arona-doc/docs/install/chat-command.md: -------------------------------------------------------------------------------- 1 | # 安装chat-command 2 | 3 | 我也不知道为什么要单独抽出来 4 | 5 | 它的[仓库地址是这个](https://github.com/project-mirai/chat-command) 6 | 7 | 可以通过mcl安装,或者直接在release下载最新版本的chat-command-0.6.0.mirai2.jar放到`plugins`文件夹 8 | 9 | 推荐使用手动安装的方式,mcl安装只能安装`0.5.1`版本的,`0.6.0`提供了更详细的配置和提示信息 10 | -------------------------------------------------------------------------------- /arona-doc/docs/install/qa.md: -------------------------------------------------------------------------------- 1 | # 疑难问题 2 | 3 | ## 8.9.63协议code=45 4 | 5 | 2023-10-10更新 6 | 7 | 目前即使是`8.9.63`版本也出现了大规模拉闸的现象(code=45),需要升级更高的版本协议,但是`fix-protocol-version`仓库下只有最高`8.9.63`协议 8 | 9 | 如果需要更高版本的协议,可以去这个仓库下载[MrXiaoM/qsign](https://github.com/MrXiaoM/qsign/tree/mirai/txlib) 10 | 11 | 在`txlib`文件夹下以版本命名的文件夹中的`android_phone.json`和`android_pad.json`即是对应版本的协议 12 | 13 | ::: warning 14 | 15 | 虽然升级协议版本能够解决问题,但是协议版本越高检测越严格,建议一个个往上试 16 | 17 | ::: 18 | 19 | 以`8.9.68`协议版本为例 20 | 21 | 1. 下载其中的`android_phone.json`并放到`mcl`根目录替换原先的`8.9.63`协议版本 22 | 2. 修改`KFCFactory.json`,将`8.9.63`改为`8.9.68` 23 | 3. 修改`unidbg-fetch-qsign-xxx`的启动命令,将`bin/unidbg-fetch-qsign --basePath=txlib/8.9.63`改为`bin/unidbg-fetch-qsign --basePath=txlib/8.9.68` 24 | 4. 修改`unidbg-fetch-qsign/txlib/8.9.68`中的`config.json`,将其中的`server`和`auto_register`内容改为和`8.9.63`中的一致,如果你有修改其他地方,也可以改成一样的,但是**注意**不要修改`protocol`相关的内容 25 | 5. 启动`unidbg-fetch-qsign`,然后启动`mcl` 26 | 6. 没了 27 | -------------------------------------------------------------------------------- /arona-doc/docs/manual/index.md: -------------------------------------------------------------------------------- 1 | # 简版用户手册 2 | 3 | 直接给群友看的版本 4 | 5 | 括号中的`私`指可以不在群里执行, 私聊机器人也能有响应 6 | 7 | 具体能不能响应需要配置, 不同群问维护人去 8 | 9 | ## 1.1 活动系列(私) 10 | 11 | `/活动` 获取日服活动状态 12 | 13 | `/活动 jp` 获取日服活动列表 14 | 15 | `/活动 en` 获取国际服活动列表 16 | 17 | `/活动 cn` 获取国服活动列表 18 | 19 | ## 1.2 抽卡系列 20 | 21 | `/单抽` 单抽一次 22 | 23 | `/十连` 抽一次十连 24 | 25 | `/狗叫` 查看当前卡池最低抽出pickup次数排行榜 26 | 27 | `/历史` 查看抽卡历史记录/几抽1个3星 28 | 29 | ## 1.3 塔罗牌系列(私) 30 | 31 | `/塔罗牌` 抽取一张塔罗牌(每天结果是否相同取决于配置) 32 | 33 | ## 1.4 昵称系列 34 | 35 | `/叫我` 查询自己的昵称 36 | 37 | `/叫我 ` 将自己的昵称设置为string 38 | 39 | 昵称替换将会在 抽卡、戳一戳、塔罗牌中进行替换 40 | 41 | ## 1.5 攻略系列(私) 42 | 43 | `/攻略 ` 查询主线地图/学生攻略。 44 | 45 | 其中主线地图支持1-1至H19-3的所有图文攻略,学生支持大部分黑话。 46 | 47 | 如`/攻略 H16-2` 查询主线困难图H16-2的图文攻略。 48 | 49 | 如`/攻略 水梓` 查询白州梓(泳装)的评价(内容来源于巴哈姆特@夜喵貓貓咪喵(asaz5566a)) 50 | 51 | 如`/攻略 国际服未来视` 查看猫佬的国际服未来视 52 | 53 | `/攻略 杂图` 显示所有能查询到的杂七杂八的名称 54 | 55 | 支持模糊查询 56 | 57 | 特别地, `国际服未来视`、`国际服活动`、`日服活动`、`国际服总力`、`日服总力`、`国际服火力演习`、`日服火力演习` 会自动指向当期内容 58 | 59 | ## 1.6 游戏名记录(私) 60 | 61 | 用来找人十分方便( 62 | 63 | `/游戏名 string` 将自己的游戏名添加到记录中。 64 | 65 | `/[谁叫|谁是] string` 根据提供的字符串模糊查询游戏名包含字符串的群友并@出来。 66 | 67 | 以上命令也可以通过群私聊机器人调用,此时`谁是`指令将只提供游戏内名称并附上对应qq号。 68 | 69 | ## 2.1 复读 70 | 71 | 当群里不同的人发送同一条消息超过3次,机器人自己复读一条相同的消息 72 | 73 | ## 2.2 戳一戳回复 74 | 75 | 当戳一戳arona时随机回复一条消息 76 | 77 | ## 2.3 活动防侠推送 78 | 79 | 当活动还有1小时结束,或者在指定的配置时间时发送活动即将结束消息 80 | 81 | ## 2.4 NGA图楼推送 82 | 83 | 当NGA图楼更新时将图转发到群中 84 | -------------------------------------------------------------------------------- /arona-doc/docs/other/help.md: -------------------------------------------------------------------------------- 1 | # 帮助 2 | 3 | ## mcl-installer 4 | 5 | ```bash 6 | # 你想装java吗 默认你想 7 | Would you like to install Java? (Y/N, default: Y) 8 | # 装哪个版本的java 默认17 9 | Java version (8, 11, 17, 18), default: 17): 10 | # 装JRE还是JDK 是只装运行时还是连开发套件一起装 默认只装运行时 11 | JRE or JDK (1: JRE, 2: JDK, default: JRE): 12 | # 装几位的 默认64位 13 | Binary Architecture (default: x64): 14 | # 最新版的mcl是v2.1.2 你想下载吗 默认想 15 | The latest stable version of iTXTech MCL is 2.1.2 16 | Would you like to download it? (Y/N, default: Y) 17 | # mcl启动脚本更新完成 18 | MCL startup script has been updated. 19 | # 在控制台里用 ./mcl 启动 20 | Use ".\mcl" to start MCL. 21 | # 按回车 22 | Press Enter to exit. 23 | ``` 24 | -------------------------------------------------------------------------------- /arona-doc/docs/other/thanks.md: -------------------------------------------------------------------------------- 1 | # 鸣谢 2 | 3 | 除第一名外排名不分先后 4 | 5 | [Haythem723](https://github.com/Haythem723)(wikiru、SchaleDB爬取模块) 6 | 7 | [巴哈姆特@夜喵貓貓咪喵(asaz5566a)](https://home.gamer.com.tw/homeindex.php?owner=asaz5566a)(学生攻略) 8 | 9 | [碧蓝档案国际服情报站](https://space.bilibili.com/1585224247)(国际服信息来源1) 10 | 11 | [SchaleDB](https://lonqie.github.io/SchaleDB/)(国际服信息来源2) 12 | 13 | [wikiru](https://bluearchive.wikiru.jp/)(日服信息来源2) 14 | 15 | [碧蓝档案 GameKee](https://ba.gamekee.com/)(国际服/日服信息来源3) 16 | 17 | [bluearchive wiki](https://bluearchive.wiki/wiki/)(信息来源) 18 | 19 | [mirai](https://github.com/mamoe/mirai)(技术支持) 20 | 21 | 非正常学生研究委员会群友(陪我闲聊) 22 | -------------------------------------------------------------------------------- /arona-doc/docs/public/empty_image.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/empty_image.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/font/ResourceHanRoundedCN-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/font/ResourceHanRoundedCN-Medium.woff -------------------------------------------------------------------------------- /arona-doc/docs/public/font/U-OTF-ShinMGoUpr-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/font/U-OTF-ShinMGoUpr-Medium.woff -------------------------------------------------------------------------------- /arona-doc/docs/public/icon.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/icon.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/command/announcment.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/command/announcment.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/command/game-name.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/command/game-name.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/command/image-help.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/command/image-help.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/command/nudge.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/command/nudge.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/command/override-name1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/command/override-name1.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/command/pool-update.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/command/pool-update.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/config/db-2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/config/db-2.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/config/db-3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/config/db-3.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/config/db-4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/config/db-4.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/config/db-5-1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/config/db-5-1.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/config/db-5-2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/config/db-5-2.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/config/db-5-3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/config/db-5-3.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/config/name-guess.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/config/name-guess.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/config/nga-cid-1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/config/nga-cid-1.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/config/nga-cid-2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/config/nga-cid-2.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/config/nga-cid-3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/config/nga-cid-3.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/config/nga-uid.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/config/nga-uid.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/config/override-name2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/config/override-name2.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/guide/active-info.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/guide/active-info.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/guide/activity-calendar.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/guide/activity-calendar.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/guide/activity-notify.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/guide/activity-notify.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/guide/chapter-map.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/guide/chapter-map.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/guide/gacha.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/guide/gacha.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/guide/manage-1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/guide/manage-1.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/guide/manage-2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/guide/manage-2.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/guide/nga.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/guide/nga.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/guide/student.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/guide/student.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/guide/tarot.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/guide/tarot.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/guide/update.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/guide/update.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/apk.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/apk.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/bots.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/bots.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/network.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/network.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/network_clear.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/network_clear.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/slider_captcha.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/slider_captcha.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/slider_captcha_scan.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/slider_captcha_scan.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/slider_commit.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/slider_commit.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/slider_content.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/slider_content.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/slider_do.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/slider_do.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/slider_second_verify.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/slider_second_verify.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/slider_sms.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/slider_sms.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/slider_success.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/slider_success.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/image/install/success.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/image/install/success.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/logo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/logo.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/logo2.png -------------------------------------------------------------------------------- /arona-doc/docs/public/plana.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-doc/docs/public/plana.webp -------------------------------------------------------------------------------- /arona-doc/docs/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / 3 | User-agent: Algolia Crawler 4 | Allow: / 5 | -------------------------------------------------------------------------------- /arona-doc/docs/terms/index.md: -------------------------------------------------------------------------------- 1 | # 其他 2 | 3 | ## [其他](others) 4 | -------------------------------------------------------------------------------- /arona-doc/docs/terms/others.md: -------------------------------------------------------------------------------- 1 | 2 | 8 | -------------------------------------------------------------------------------- /arona-doc/docs/types/helper.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any,@typescript-eslint/ban-types */ 2 | 3 | type FilterOptional = Pick< 4 | T, 5 | Exclude< 6 | { 7 | [K in keyof T]: T extends Record ? K : never; 8 | }[keyof T], 9 | undefined 10 | > 11 | >; 12 | 13 | type FilterNotOptional = Pick< 14 | T, 15 | Exclude< 16 | { 17 | [K in keyof T]: T extends Record ? never : K; 18 | }[keyof T], 19 | undefined 20 | > 21 | >; 22 | 23 | type PartialEither = { 24 | [P in Exclude, K>]-?: T[P]; 25 | } & { [P in Exclude, K>]?: T[P] } & { 26 | [P in Extract]?: undefined; 27 | }; 28 | 29 | type Object = { 30 | [name: string]: any; 31 | }; 32 | 33 | export type EitherOr = ( 34 | | PartialEither, L> 35 | | PartialEither, R> 36 | ) & 37 | Omit; 38 | -------------------------------------------------------------------------------- /arona-doc/docs/utils/CJKService.ts: -------------------------------------------------------------------------------- 1 | function transformVoicedOrSemiVoiced(char: string): string { 2 | const voiced = new RegExp( 3 | /[がぎぐげござじずぜぞだぢづでどばびぶべぼぱぴぷぺぽガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポ]/g 4 | ); 5 | const semiVoiced = new RegExp(/[ぱぴぷぺぽパピプペポ]/g); 6 | 7 | return char 8 | .replace( 9 | voiced, 10 | (match) => 11 | String.fromCharCode(match.charCodeAt(0) - 1) + 12 | String.fromCharCode(0x3099) 13 | ) 14 | .replace( 15 | semiVoiced, 16 | (match) => 17 | String.fromCharCode(match.charCodeAt(0) - 1) + 18 | String.fromCharCode(0x309a) 19 | ); 20 | } 21 | 22 | export { transformVoicedOrSemiVoiced }; 23 | -------------------------------------------------------------------------------- /arona-doc/docs/utils/anchorPositioningService.ts: -------------------------------------------------------------------------------- 1 | import { matchElementByHash } from './hashMatchingService'; 2 | 3 | function isInViewport(el: HTMLElement) { 4 | const rect = el.getBoundingClientRect(); 5 | return ( 6 | rect.top >= 0 && 7 | rect.left >= 0 && 8 | rect.bottom <= 9 | (window.innerHeight || document.documentElement.clientHeight) && 10 | rect.right <= (window.innerWidth || document.documentElement.clientWidth) 11 | ); 12 | } 13 | 14 | function scrollElementIntoView(element: HTMLElement, immediate = true) { 15 | const offsetTime = immediate ? 0 : 500; 16 | setTimeout(() => { 17 | if (!isInViewport(element)) { 18 | const top = element.offsetTop; 19 | 20 | window.scrollTo({ 21 | top: top, 22 | }); 23 | } 24 | }, offsetTime); 25 | } 26 | 27 | export function scrollElementIntoViewAfterMounted() { 28 | const hash = decodeURIComponent(window.location.hash).slice(1); 29 | if (hash) { 30 | const elements = document.querySelectorAll("h2, h3, h4, h5, h6"); 31 | const element = matchElementByHash(hash, elements); 32 | if (element) { 33 | scrollElementIntoView(element); 34 | } 35 | } 36 | } 37 | 38 | export { scrollElementIntoView, isInViewport }; 39 | -------------------------------------------------------------------------------- /arona-doc/docs/utils/hashMatchingService.ts: -------------------------------------------------------------------------------- 1 | import { transformVoicedOrSemiVoiced } from "./CJKService"; 2 | 3 | function matchElementByHash( 4 | decodedHash: string, 5 | elements: NodeListOf 6 | ): HTMLElement | undefined { 7 | const transformedHash = transformVoicedOrSemiVoiced(decodedHash); 8 | const elementList = Array.from(elements).filter( 9 | (element) => transformedHash === element.id 10 | ); 11 | 12 | return elementList.length > 0 ? (elementList[0] as HTMLElement) : undefined; 13 | } 14 | 15 | export { matchElementByHash }; 16 | -------------------------------------------------------------------------------- /arona-doc/docs/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import AutoImport from "unplugin-auto-import/vite"; 3 | import Components from "unplugin-vue-components/vite"; 4 | import { ElementPlusResolver } from "unplugin-vue-components/resolvers"; 5 | import Icons from "unplugin-icons/vite"; 6 | import IconsResolver from "unplugin-icons/resolver"; 7 | // https://vitejs.dev/config/ 8 | import path from "path"; 9 | const pathSrc = path.resolve(__dirname, "docs"); 10 | 11 | export default defineConfig({ 12 | ssr: { noExternal: ["element-plus"] }, 13 | resolve: { 14 | alias: { 15 | "@": pathSrc, 16 | }, 17 | }, 18 | plugins: [ 19 | AutoImport({ 20 | resolvers: [ 21 | ElementPlusResolver(), 22 | IconsResolver({ 23 | prefix: "Icon", 24 | }), 25 | ], 26 | dts: path.resolve(pathSrc, "auto-imports.d.ts"), 27 | }), 28 | Components({ 29 | resolvers: [ 30 | ElementPlusResolver(), 31 | IconsResolver({ 32 | enabledCollections: ["ep"], 33 | }), 34 | ], 35 | dts: path.resolve(pathSrc, "components.d.ts"), 36 | }), 37 | Icons({ 38 | autoInstall: true, 39 | }), 40 | ], 41 | }); 42 | -------------------------------------------------------------------------------- /arona-doc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "resolveJsonModule": true, 10 | "isolatedModules": true, 11 | "esModuleInterop": true, 12 | "lib": ["ESNext", "DOM"], 13 | "skipLibCheck": true, 14 | "noEmit": true 15 | }, 16 | "include": ["docs/**/*.ts", "docs/**/*.d.ts", "docs/**/*.tsx", "docs/**/*.vue"], 17 | "references": [{ "path": "./tsconfig.node.json" }] 18 | } 19 | -------------------------------------------------------------------------------- /arona-doc/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /arona-webui-frontend/.commitlintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | 'type-enum': [ 5 | 2, 6 | 'always', 7 | ['init', 'build', 'ci', 'chore', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test'], 8 | ], 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /arona-webui-frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] # 表示所有文件都要遵循 7 | indent_style = space # 缩进风格,可选配置有space和tab 8 | indent_size = 2 # 缩进大小 9 | end_of_line = lf # 换行符,可选配置有lf、cr和crlf 10 | charset = utf-8 # 编码格式,通常都是选utf-8 11 | trim_trailing_whitespace = true # 去除多余的空格 12 | insert_final_newline = true # 在尾部插入一行 13 | 14 | [*.md] # 表示仅 md 文件适用 15 | insert_final_newline = false # 在尾部插入一行 16 | trim_trailing_whitespace = false # 去除多余的空格 17 | -------------------------------------------------------------------------------- /arona-webui-frontend/.env: -------------------------------------------------------------------------------- 1 | VITE_API_BASEURL = http://127.0.0.1:8080/api/v1 2 | 3 | VITE_BASE = / 4 | 5 | VITE_APP_TITLE = AronaConfigWebUI 6 | 7 | VITE_APP_DESCRIPTION = A zero-config Vue3 template includes Vite3、Vue3 and TypeScript 8 | -------------------------------------------------------------------------------- /arona-webui-frontend/.env.development: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/.env.development -------------------------------------------------------------------------------- /arona-webui-frontend/.env.production: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/.env.production -------------------------------------------------------------------------------- /arona-webui-frontend/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | presets 7 | *.d.ts 8 | gstc.wasm.esm.min.js 9 | -------------------------------------------------------------------------------- /arona-webui-frontend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | node: true, 6 | }, 7 | globals: { 8 | defineEmits: true, 9 | document: true, 10 | localStorage: true, 11 | GLOBAL_VAR: true, 12 | window: true, 13 | defineProps: true, 14 | defineExpose: true, 15 | withDefaults: true, 16 | }, 17 | extends: [ 18 | "./.eslintrc-auto-import.json", 19 | "airbnb-base", 20 | "plugin:@typescript-eslint/recommended", 21 | "plugin:vue/vue3-recommended", 22 | "plugin:prettier/recommended", // 添加 prettier 插件 23 | ], 24 | parserOptions: { 25 | ecmaVersion: "latest", 26 | parser: "@typescript-eslint/parser", 27 | sourceType: "module", 28 | }, 29 | plugins: ["vue", "@typescript-eslint", "import"], 30 | rules: { 31 | "no-console": "off", 32 | "no-plusplus": "off", 33 | "no-param-reassign": "off", 34 | "import/extensions": "off", 35 | "no-use-before-define": "off", 36 | "import/no-unresolved": "off", 37 | "import/no-extraneous-dependencies": "off", 38 | "@typescript-eslint/ban-ts-comment": "off", 39 | "@typescript-eslint/no-non-null-assertion": "off", 40 | "no-shadow": "off", 41 | "@typescript-eslint/no-shadow": ["error"], 42 | "no-underscore-dangle": "off", // 允许使用带有下划线的成员变量, this._foo 表明这是一个私有变量 43 | }, 44 | }; 45 | -------------------------------------------------------------------------------- /arona-webui-frontend/.fleet/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "backend.maxHeapSizeMb": 896 3 | } -------------------------------------------------------------------------------- /arona-webui-frontend/.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | 7 | # Declare files that will always have CRLF line endings on checkout. 8 | *.vue text eol=lf 9 | *.ts text eol=lf 10 | *.js text eol=lf 11 | *.scss text eol=lf 12 | 13 | # Denote all files that are truly binary and should not be modified. 14 | *.png binary 15 | *.jpg binary 16 | *.webp binary 17 | *.svg binary 18 | *.woff binary 19 | *.woff2 binary 20 | *.yaml binary 21 | *.json binary 22 | *.json binary 23 | -------------------------------------------------------------------------------- /arona-webui-frontend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | .idea 7 | dist.7z 8 | -------------------------------------------------------------------------------- /arona-webui-frontend/.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /arona-webui-frontend/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | *.d.ts 7 | -------------------------------------------------------------------------------- /arona-webui-frontend/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 diyigemt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /arona-webui-frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /arona-webui-frontend/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello": "Hello", 3 | "welcome to": "Welcome to", 4 | "includes features": "is a zero-config Vue3 template, it includes these feature:", 5 | "before coding": "Before coding", 6 | "setup ide": "I recommended your IDE setup", 7 | "home": "Home", 8 | "change light": "Click to switch to bright color theme", 9 | "change dark": "Click to switch to dark theme", 10 | "change lang": "Switch languages", 11 | "method to using": "Method of using template", 12 | "template process": "Template configuration process", 13 | "config": { 14 | "arona": { 15 | "desc": "this is arona's main config" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /arona-webui-frontend/locales/zh-cn.json: -------------------------------------------------------------------------------- 1 | { 2 | "home": "主页", 3 | "change light": "点击切换为亮色主题", 4 | "change dark": "点击切换为暗黑主题", 5 | "change lang": "切换国际化语言", 6 | "method to using": "使用模板的方法", 7 | "template process": "模板配置流程", 8 | "config": { 9 | "arona": { 10 | "desc": "arona主配置文件" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/controller/blockly.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from "express"; 2 | import { packageResponse } from "../utils"; 3 | import { BlocklyProject } from "../../src/interface/modules/blockly"; 4 | // eslint-disable-next-line import/prefer-default-export 5 | export function getBlocklyProject(_: Request, response: Response): Promise { 6 | return new Promise((resolve) => { 7 | setTimeout(() => { 8 | const data: BlocklyProject[] = []; 9 | resolve(packageResponse(response, data)); 10 | }, 50); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/controller/file.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from "express"; 2 | import { UploadedFile } from "express-fileupload"; 3 | import { packageResponse, packageResponseError } from "../utils"; 4 | 5 | // eslint-disable-next-line import/prefer-default-export 6 | export function uploadImage(request: Request, response: Response): Promise { 7 | return new Promise((resolve) => { 8 | if (request.files && request.files.file) { 9 | const file = request.files.file as UploadedFile; 10 | const fileName = request.header("arona-file-name") 11 | ? decodeURI(request.header("arona-file-name") as string) 12 | : file.name; 13 | file.mv(`${__dirname}/files/${fileName}`).then(() => { 14 | resolve(packageResponse(response, "1000002")); 15 | }); 16 | } else { 17 | resolve(packageResponseError(response, "没有文件")); 18 | } 19 | }); 20 | } 21 | 22 | const fileDict: Record = { 23 | "1000001": "rua.png", 24 | "1000002": "neko.png", 25 | }; 26 | 27 | export function getFileById(request: Request, response: Response) { 28 | const id = request.query.id as string; 29 | response.sendFile(`${__dirname}/files/${fileDict[id]}`); 30 | } 31 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/controller/files/neko.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/mock/controller/files/neko.png -------------------------------------------------------------------------------- /arona-webui-frontend/mock/controller/files/rua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/mock/controller/files/rua.png -------------------------------------------------------------------------------- /arona-webui-frontend/mock/controller/mirai.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from "express"; 2 | import { packageResponse } from "../utils"; 3 | import { Friend, User } from "../../src/types/contact"; 4 | // eslint-disable-next-line import/prefer-default-export 5 | export function getBotList(_: Request, response: Response): Promise { 6 | return new Promise((resolve) => { 7 | const data: Friend[] = [ 8 | { 9 | id: 12313123, 10 | name: "测试用机器人", 11 | remark: "", 12 | }, 13 | { 14 | id: 22232233, 15 | name: "测试用机器人2", 16 | remark: "", 17 | }, 18 | ]; 19 | setTimeout(() => { 20 | resolve(packageResponse(response, data)); 21 | }, 50); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/controller/ping.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from "express"; 2 | import { packageResponse } from "../utils"; 3 | // eslint-disable-next-line import/prefer-default-export 4 | export function ping(_: Request, response: Response): Promise { 5 | return new Promise((resolve) => { 6 | setTimeout(() => { 7 | resolve(packageResponse(response, "pong")); 8 | }, 50); 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/index.d.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/mock/index.d.ts -------------------------------------------------------------------------------- /arona-webui-frontend/mock/index.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | // @ts-ignore 3 | import cors from "cors"; 4 | import bodyParser from "body-parser"; 5 | // @ts-ignore 6 | import fileUpload from "express-fileupload"; 7 | import http from "http"; 8 | import router from "./routes"; 9 | 10 | function main() { 11 | const app = express(); 12 | const port = 13801; 13 | app.use(bodyParser.json()); 14 | app.use(cors()); 15 | app.use( 16 | fileUpload({ 17 | createParentPath: true, 18 | uriDecodeFileNames: true, 19 | }), 20 | ); 21 | app.use("/api/v1", router); 22 | try { 23 | const httpServer = http.createServer(app); 24 | httpServer.listen(port, () => { 25 | console.info(`Http Server running on http://localhost:${port}`); 26 | }); 27 | } catch (error: any) { 28 | console.error(`Http Error occurred: ${error.message}`); 29 | } 30 | } 31 | 32 | main(); 33 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/routes/blockly.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { getBlocklyProject } from "../controller/blockly"; 3 | 4 | const BlocklyRouter = Router(); 5 | 6 | BlocklyRouter.get("/commit", getBlocklyProject); 7 | 8 | export default BlocklyRouter; 9 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/routes/config.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { getConfig } from "../controller/config"; 3 | 4 | const ConfigRouter = Router(); 5 | 6 | ConfigRouter.get("/", getConfig); 7 | 8 | export default ConfigRouter; 9 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/routes/contact.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { getContactList } from "../controller/contact"; 3 | 4 | const ContactRouter = Router(); 5 | 6 | ContactRouter.get("/", getContactList); 7 | 8 | export default ContactRouter; 9 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/routes/file.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { getFileById, uploadImage } from "../controller/file"; 3 | 4 | const FileRouter = Router(); 5 | 6 | FileRouter.post("/image", uploadImage); 7 | FileRouter.get("/image", getFileById); 8 | 9 | export default FileRouter; 10 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/routes/index.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import ContactRouter from "./contact"; 3 | import PingRouter from "./ping"; 4 | import BlocklyRouter from "./blockly"; 5 | import ConfigRouter from "./config"; 6 | import ReplyRouter from "./reply"; 7 | import FileRouter from "./file"; 8 | import MiraiRouter from "./mirai"; 9 | 10 | const router = Router(); 11 | 12 | router.use("/contacts", ContactRouter); 13 | router.use("/ping", PingRouter); 14 | router.use("/blockly", BlocklyRouter); 15 | router.use("/config", ConfigRouter); 16 | router.use("/reply", ReplyRouter); 17 | router.use("/file", FileRouter); 18 | router.use("/mirai", MiraiRouter); 19 | 20 | export default router; 21 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/routes/mirai.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { getBotList } from "../controller/mirai"; 3 | 4 | const MiraiRouter = Router(); 5 | 6 | MiraiRouter.get("/bot", getBotList); 7 | 8 | export default MiraiRouter; 9 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/routes/ping.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { getContactList } from "../controller/contact"; 3 | import {ping} from "../controller/ping"; 4 | 5 | const PingRouter = Router(); 6 | 7 | PingRouter.get("/", ping); 8 | 9 | export default PingRouter; 10 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/routes/reply.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { getReplyGroup, getReplyLabel } from "../controller/reply"; 3 | 4 | const ReplyRouter = Router(); 5 | 6 | ReplyRouter.get("/group", getReplyGroup); 7 | ReplyRouter.get("/label", getReplyLabel); 8 | 9 | export default ReplyRouter; 10 | -------------------------------------------------------------------------------- /arona-webui-frontend/mock/utils/index.ts: -------------------------------------------------------------------------------- 1 | import { Response } from "express"; 2 | import { HTTP_ERROR, HTTP_OK } from "../../src/constant/http"; 3 | 4 | export function packageResponseNull(response: Response) { 5 | return response.status(HTTP_OK).send(constructMessage(HTTP_OK, null)); 6 | } 7 | 8 | export function packageResponse(response: Response, data: T) { 9 | return response.status(HTTP_OK).send(constructMessage(HTTP_OK, data)); 10 | } 11 | 12 | export function packageResponseError(response: Response, message: string) { 13 | return response.status(HTTP_ERROR).send(constructMessage(HTTP_OK, null, message)); 14 | } 15 | 16 | export function constructMessage(code: number, data: T, message = "") { 17 | return { code, data: data || ("" as any), message }; 18 | } 19 | -------------------------------------------------------------------------------- /arona-webui-frontend/prettier.config.js: -------------------------------------------------------------------------------- 1 | // https://prettier.io/docs/en/configuration.html 2 | module.exports = { 3 | // 每一行的宽度(显示的字符数) 4 | printWidth: 120, 5 | 6 | // tab健的空格数 7 | tabWidth: 2, 8 | 9 | // 是否在对象中的括号之间打印空格,{a:5}格式化为{ a: 5 } 10 | bracketSpacing: true, 11 | 12 | // 箭头函数的参数无论有几个,都要括号包裹 13 | arrowParens: "always", 14 | 15 | // 换行符的使用 16 | endOfLine: "lf", 17 | 18 | // 是否用单引号, 项目中全部使用双引号 19 | singleQuote: false, 20 | 21 | // 对象或者数组的最后一个元素后面是否要加逗号 22 | trailingComma: "all", 23 | 24 | // 是否加分号,项目中统一加分号 25 | semi: true, 26 | 27 | // 是否使用tab格式化: 不使用 28 | useTabs: false, 29 | }; 30 | -------------------------------------------------------------------------------- /arona-webui-frontend/public/blockly/toolbox.xml: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /arona-webui-frontend/public/blockly/workspace.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /arona-webui-frontend/public/font/ResourceHanRoundedCN-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/font/ResourceHanRoundedCN-Medium.ttf -------------------------------------------------------------------------------- /arona-webui-frontend/public/font/ResourceHanRoundedCN-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/font/ResourceHanRoundedCN-Medium.woff -------------------------------------------------------------------------------- /arona-webui-frontend/public/font/U-OTF-ShinMGoUpr-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/font/U-OTF-ShinMGoUpr-Medium.woff -------------------------------------------------------------------------------- /arona-webui-frontend/public/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/icon.jpg -------------------------------------------------------------------------------- /arona-webui-frontend/public/image/BG_CS_PR_01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/image/BG_CS_PR_01.jpg -------------------------------------------------------------------------------- /arona-webui-frontend/public/image/BG_CS_PR_03.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/image/BG_CS_PR_03.jpg -------------------------------------------------------------------------------- /arona-webui-frontend/public/image/BG_CS_PR_05.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/image/BG_CS_PR_05.jpg -------------------------------------------------------------------------------- /arona-webui-frontend/public/image/BG_HQ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/image/BG_HQ.jpg -------------------------------------------------------------------------------- /arona-webui-frontend/public/image/BG_View_Kivotos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/image/BG_View_Kivotos.jpg -------------------------------------------------------------------------------- /arona-webui-frontend/public/image/FX_TEX_Arona_A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/image/FX_TEX_Arona_A.png -------------------------------------------------------------------------------- /arona-webui-frontend/public/image/FX_TEX_Arona_B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/image/FX_TEX_Arona_B.png -------------------------------------------------------------------------------- /arona-webui-frontend/public/image/FX_TEX_Arona_C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/image/FX_TEX_Arona_C.png -------------------------------------------------------------------------------- /arona-webui-frontend/public/image/FX_TEX_Arona_Stand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/image/FX_TEX_Arona_Stand.png -------------------------------------------------------------------------------- /arona-webui-frontend/public/image/FX_TEX_Triangle_02_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/image/FX_TEX_Triangle_02_a.png -------------------------------------------------------------------------------- /arona-webui-frontend/public/image/arona_home_poster.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/image/arona_home_poster.jpg -------------------------------------------------------------------------------- /arona-webui-frontend/public/image/poli-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/image/poli-light.png -------------------------------------------------------------------------------- /arona-webui-frontend/public/spine/arona_spr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/spine/arona_spr.png -------------------------------------------------------------------------------- /arona-webui-frontend/public/spine/arona_spr.skel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/spine/arona_spr.skel -------------------------------------------------------------------------------- /arona-webui-frontend/public/spine/arona_workpage_daytime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/spine/arona_workpage_daytime.png -------------------------------------------------------------------------------- /arona-webui-frontend/public/spine/arona_workpage_daytime.skel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/spine/arona_workpage_daytime.skel -------------------------------------------------------------------------------- /arona-webui-frontend/public/spine/arona_workpage_daytime2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/spine/arona_workpage_daytime2.png -------------------------------------------------------------------------------- /arona-webui-frontend/public/spine/arona_workpage_nighttime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/spine/arona_workpage_nighttime.png -------------------------------------------------------------------------------- /arona-webui-frontend/public/spine/arona_workpage_nighttime.skel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/spine/arona_workpage_nighttime.skel -------------------------------------------------------------------------------- /arona-webui-frontend/public/spine/arona_workpage_nighttime2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/spine/arona_workpage_nighttime2.png -------------------------------------------------------------------------------- /arona-webui-frontend/public/video/arona_desk.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/video/arona_desk.mp4 -------------------------------------------------------------------------------- /arona-webui-frontend/public/video/arona_look.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/video/arona_look.mp4 -------------------------------------------------------------------------------- /arona-webui-frontend/public/video/arona_sleep.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/public/video/arona_sleep.mp4 -------------------------------------------------------------------------------- /arona-webui-frontend/src/api/code.ts: -------------------------------------------------------------------------------- 1 | declare interface codeMessageMapTypes { 2 | 400: string; 3 | 401: string; 4 | 403: string; 5 | 404: string; 6 | 405: string; 7 | 500: string; 8 | [key: string]: string; 9 | } 10 | 11 | const codeMessageMap: codeMessageMapTypes = { 12 | 400: "[400]:请求参数错误", 13 | 401: "[401]:账户未登录", 14 | 403: "[403]:拒绝访问", 15 | 404: "[404]:请求路径错误", 16 | 405: "[405]:请求方法错误", 17 | 500: "[500]:服务器错误", 18 | }; 19 | 20 | const showCodeMessage = (code: number | string): string => { 21 | return codeMessageMap[JSON.stringify(code)] || "网络连接异常,请稍后再试!"; 22 | }; 23 | 24 | export default showCodeMessage; 25 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/api/http.ts: -------------------------------------------------------------------------------- 1 | import useSettingStore from "@/store/setting"; 2 | import { ApiServiceAdapter, NetworkAdapterType } from "@/interface/http"; 3 | import LocalhostService from "@/api/adapter/localhost"; 4 | 5 | const ServiceHandler: ProxyHandler = { 6 | get(_, key) { 7 | const settingStore = useSettingStore(); 8 | const adapter = Reflect.get(AdapterMap, settingStore.adapter) || LocalhostService; 9 | return Reflect.get(adapter, key); 10 | }, 11 | }; 12 | type AdapterMap = { 13 | [key in NetworkAdapterType]: ApiServiceAdapter; 14 | }; 15 | // TODO 16 | const AdapterMap: AdapterMap = { 17 | Localhost: LocalhostService, 18 | Offline: LocalhostService, 19 | Proxy: LocalhostService, 20 | }; 21 | 22 | const service = new Proxy(LocalhostService, ServiceHandler); 23 | 24 | export default service; 25 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/api/index.ts: -------------------------------------------------------------------------------- 1 | import { successMessage } from "@/utils/message"; 2 | import service from "./http"; 3 | import emitter from "@/utils/config/emitter"; 4 | 5 | // eslint-disable-next-line import/prefer-default-export 6 | export function heartbeat() { 7 | return new Promise((resolve) => { 8 | service 9 | .raw({ 10 | url: "/ping", 11 | method: "GET", 12 | showResponseError: false, 13 | }) 14 | .then((res) => { 15 | if (res.data === "pong") { 16 | successMessage("连接成功"); 17 | emitter.emit("api-update"); 18 | resolve(true); 19 | } 20 | resolve(false); 21 | }) 22 | .catch(() => { 23 | resolve(false); 24 | }); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/api/modules/blockly.ts: -------------------------------------------------------------------------------- 1 | import { BlocklyProject } from "@/interface/modules/blockly"; 2 | import service from "@/api/http"; 3 | 4 | const BlocklyApi = { 5 | fetchBlocklyProjectList() { 6 | return service.raw({ 7 | url: "/blockly/commit", 8 | method: "GET", 9 | }); 10 | }, 11 | saveBlocklyProject(data: BlocklyProjectSaveData) { 12 | return service.raw({ 13 | url: "/blockly/commit", 14 | method: "POST", 15 | data: { 16 | mode: "CREATE", 17 | ...data, 18 | }, 19 | }); 20 | }, 21 | 22 | updateBlocklyProject(data: BlocklyProjectSaveData) { 23 | return service.raw({ 24 | url: "/blockly/commit", 25 | method: "POST", 26 | data: { 27 | mode: "UPDATE", 28 | ...data, 29 | }, 30 | }); 31 | }, 32 | 33 | deleteBlocklyProject(data: BlocklyProjectSaveData) { 34 | return service.raw({ 35 | url: "/blockly/commit", 36 | method: "POST", 37 | data: { 38 | mode: "DELETE", 39 | ...data, 40 | }, 41 | }); 42 | }, 43 | }; 44 | 45 | export default BlocklyApi; 46 | 47 | interface BlocklyProjectSaveData { 48 | trigger: string; 49 | uuid: string | null; 50 | projectName: string; 51 | blocklyProject: string; 52 | userData: UserData | string; 53 | } 54 | 55 | export interface UserData { 56 | groups: number[]; 57 | } 58 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/api/modules/config.ts: -------------------------------------------------------------------------------- 1 | import service from "@/api/http"; 2 | import { ServerAronaConfig } from "@/interface"; 3 | 4 | const ConfigApi = { 5 | fetchConfig() { 6 | return service.raw({ 7 | url: "/config", 8 | method: "GET", 9 | }); 10 | }, 11 | }; 12 | 13 | export default ConfigApi; 14 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/api/modules/contact.ts: -------------------------------------------------------------------------------- 1 | import service from "@/api/http"; 2 | import { Member } from "@/types/contact"; 3 | import { BotContact } from "@/interface/modules/contact"; 4 | 5 | const ContactApi = { 6 | /** 7 | * 根据bot实例获取bot加入的群以及好友 8 | * @returns bot加入的群信息 9 | */ 10 | fetchBotContacts() { 11 | return service.raw({ 12 | url: "/contacts", 13 | method: "GET", 14 | }); 15 | }, 16 | /** 17 | * 获取一个群的所有联系人列表 18 | * @param group 群id 19 | * @param bot 通过指定的bot获取 20 | */ 21 | fetchGroupMember(group: number, bot?: number) { 22 | return service.raw({ 23 | url: `/contacts/${group}`, 24 | method: "POST", 25 | data: { 26 | group, 27 | bot, 28 | }, 29 | }); 30 | }, 31 | }; 32 | 33 | export default ContactApi; 34 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/api/modules/db.ts: -------------------------------------------------------------------------------- 1 | import service from "@/api/http"; 2 | import { AvailableDB } from "@/interface/modules/db"; 3 | import { GachaPool } from "@/interface/modules/gacha"; 4 | 5 | const DBApi = { 6 | queryDefaultDB(name: AvailableDB) { 7 | return service.raw({ 8 | url: `/db/default/${name}`, 9 | }); 10 | }, 11 | queryGachaPool() { 12 | return this.queryDefaultDB(AvailableDB.GachaPools); 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/api/modules/file.ts: -------------------------------------------------------------------------------- 1 | import service from "@/api/http"; 2 | import {currentAPI} from "@/api/adapter/localhost"; 3 | 4 | const FileApi = { 5 | buildFileDownloadPath(id: string) { 6 | return `${currentAPI()}/api/v1/file/image?id=${id}`; 7 | }, 8 | fetchFileById(id: string) { 9 | return service.download(id); 10 | }, 11 | }; 12 | 13 | export default FileApi; 14 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/api/modules/mirai.ts: -------------------------------------------------------------------------------- 1 | import service from "@/api/http"; 2 | import { Friend } from "@/types/contact"; 3 | 4 | const MiraiApi = { 5 | fetchBotList() { 6 | return service.raw({ 7 | url: "/mirai/bot", 8 | method: "GET", 9 | }); 10 | }, 11 | }; 12 | 13 | export default MiraiApi; 14 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/assets/styles/dark.scss: -------------------------------------------------------------------------------- 1 | body { 2 | @apply text-gray-700 dark: bg-gray-800 dark:text-gray-200; 3 | } 4 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/assets/styles/variables.scss: -------------------------------------------------------------------------------- 1 | $theme-color: #2080F0FF 2 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/blockly/index.ts: -------------------------------------------------------------------------------- 1 | import { BlocklyOptions } from "blockly"; 2 | import addBlocks from "@/blockly/blocks"; 3 | import addMutators from "@/blockly/mutators"; 4 | import injectExtensions from "@/blockly/extensions"; 5 | 6 | const BlocklyConfig: BlocklyOptions = { 7 | media: "/media/", 8 | grid: { 9 | spacing: 25, 10 | length: 3, 11 | colour: "#ccc", 12 | snap: true, 13 | }, 14 | disable: false, 15 | toolbox: await getXML("/blockly/toolbox.xml", "toolbox"), 16 | maxInstances: {}, 17 | theme: "Zelos", 18 | }; 19 | 20 | async function getXML(url: string, id: string): Promise { 21 | return fetch(url) 22 | .then((response) => { 23 | return response.text(); 24 | }) 25 | .then((str) => { 26 | return new DOMParser().parseFromString(str, "text/xml").getElementById(id) as HTMLElement; 27 | }); 28 | } 29 | 30 | export const workspaceBlocks = await getXML("/blockly/workspace.xml", "workspaceBlocks"); 31 | 32 | export const blocks = JSON.parse( 33 | await fetch("/blockly/blocks.json").then((response) => { 34 | return response.text(); 35 | }), 36 | ); 37 | 38 | export function initBlockly() { 39 | addBlocks(); 40 | addMutators(); 41 | injectExtensions(); 42 | } 43 | 44 | export default BlocklyConfig; 45 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/blockly/mutators.ts: -------------------------------------------------------------------------------- 1 | import MasterBlockMutator from "@/blockly/mutators/MasterBlockMutator"; 2 | import BlocklyUtil from "@/blockly/BlocklyUtil"; 3 | 4 | export default function addMutators() { 5 | BlocklyUtil.registerMixin("masterBlockMutator", new MasterBlockMutator()); 6 | } 7 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/blockly/mutators/MasterBlockMutator.ts: -------------------------------------------------------------------------------- 1 | import AbstractMutator, { MutatorBlockSvg } from "@/blockly/mutators/AbstractMutator"; 2 | 3 | export default class MasterBlockMutator extends AbstractMutator { 4 | controlsHelper(this: MutatorBlockSvg): void { 5 | this.getInput("Expressions0")!.insertFieldAt(0, MasterBlockMutator.createPlusField(), "plus"); 6 | } 7 | 8 | addPart(this: MutatorBlockSvg) { 9 | this.itemCount++; 10 | this.appendValueInput(`Expressions${this.itemCount}`) 11 | .appendField(MasterBlockMutator.createMinusField(), "minus") 12 | .appendField(" 当"); 13 | 14 | this.appendStatementInput(`Actions${this.itemCount}`).appendField("执行"); 15 | } 16 | 17 | removePart(this: MutatorBlockSvg) { 18 | if (this.itemCount !== 0) { 19 | const input = this.getInput(`Expressions${this.itemCount}`)!.connection!; 20 | if (input.isConnected()) input.disconnect(); 21 | this.removeInput(`Expressions${this.itemCount}`); 22 | this.removeInput(`Actions${this.itemCount}`); 23 | this.itemCount--; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/blockly/serializer.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/arona-webui-frontend/src/blockly/serializer.ts -------------------------------------------------------------------------------- /arona-webui-frontend/src/components/EnProcess.md: -------------------------------------------------------------------------------- 1 | ## Try it now! 2 | 3 | ### GitHub Template 4 | 5 | [Create a repo from this template on GitHub](https://github.com/nekobc1998923/vitecamp/generate). 6 | 7 | ### Clone to local 8 | 9 | ```bash 10 | git clone https://github.com/nekobc1998923/vitecamp.git my-vitecamp-app 11 | cd my-vitecamp-app 12 | pnpm i 13 | ``` 14 | 15 | ## Checklist 16 | 17 | When you use this template, try follow the checklist to update your info properly 18 | 19 | - Change the author name in `LICENSE` 20 | - Change the author name in `package.json` 21 | - Change the title in `.env` 22 | - Change the favicon in `public` 23 | - Clean up the `README` and remove routes 24 | 25 | And then , you can enjoy coding fun :) 26 | 27 | ## Usage 28 | 29 | ### Development 30 | 31 | Just run and visit http://localhost:8080 32 | 33 | ```bash 34 | pnpm run dev 35 | ``` 36 | 37 | ### Build 38 | 39 | To build the App, run 40 | 41 | ```bash 42 | pnpm run build 43 | ``` 44 | 45 | And you will see the generated file in `dist` that ready to be served. 46 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/components/MainBanner.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 26 | 27 | 51 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/components/PageHeader.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 24 | 25 | 34 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/components/ShadowCard.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | 25 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/components/SubPageIndex.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/components/ZhProcess.md: -------------------------------------------------------------------------------- 1 | ## 现在可以试试! 2 | 3 | ### GitHub 模板 4 | 5 | [使用这个模板创建仓库](https://github.com/nekobc1998923/vitecamp/generate). 6 | 7 | ### 克隆到本地 8 | 9 | ```bash 10 | git clone https://github.com/nekobc1998923/vitecamp.git my-vitecamp-app 11 | cd my-vitecamp-app 12 | pnpm i 13 | ``` 14 | 15 | ## 清单 16 | 17 | 使用此模板时,请尝试按照清单正确更新您自己的信息 18 | 19 | - 在 `LICENSE` 中改变作者名 20 | - 在 `package.json` 中改变作者名 21 | - 在 `.env` 中改变标题 22 | - 在 `public` 目录下改变 favicon 23 | - 整理 `README `并删除路由 24 | 25 | 然后,你就可以享受编写代码的乐趣了 :) 26 | 27 | ## 使用 28 | 29 | ### 开发 30 | 31 | 只需要执行以下命令就可以在 http://localhost:8080 中看到 32 | 33 | ```bash 34 | pnpm run dev 35 | ``` 36 | 37 | ### 构建 38 | 39 | 构建该应用只需要执行以下命令 40 | 41 | ```bash 42 | pnpm run build 43 | ``` 44 | 45 | 然后你会看到用于发布的 `dist` 文件夹被生成。 46 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/constant/config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | bots: true, 3 | managerGroup: true, 4 | everyDayHour: true, 5 | onlineMessage: false, 6 | offlineMessage: false, 7 | permissionDeniedMessage: false, 8 | }; 9 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/constant/http.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/prefer-default-export 2 | export const HTTP_OK = 200; 3 | export const HTTP_ERROR = 100; 4 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/constant/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./http"; 2 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/env.d.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | /// 3 | /// 4 | // 声明自动引入的 vue 组件 5 | // @ts-ignore 6 | // @ts-ignore 7 | 8 | import { App } from "vue"; 9 | import {Block} from "blockly"; 10 | 11 | declare module '*.vue' { 12 | import { DefineComponent } from "vue"; 13 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 14 | const component: DefineComponent<{}, {}, any>; 15 | export default component; 16 | } 17 | 18 | // 声明 icons 引入的组件 19 | declare module '~icons/*' { 20 | import { FunctionalComponent, SVGAttributes } from "vue"; 21 | const component: FunctionalComponent; 22 | export default component; 23 | } 24 | 25 | // 声明 md 文件 26 | declare module '*.md' { 27 | import type { DefineComponent } from "vue"; 28 | const component: DefineComponent<{}, {}, any>; 29 | export default component; 30 | } 31 | 32 | // 声明 vite 环境变量 33 | declare interface ImportMetaEnv { 34 | readonly VITE_BASE: string; 35 | readonly VITE_API_BASEURL: string; 36 | readonly VITE_APP_TITLE: string; 37 | // 更多环境变量... 38 | } 39 | 40 | declare interface ImportMeta { 41 | readonly env: ImportMetaEnv; 42 | } 43 | 44 | type SelectType = "friend"; 45 | interface ExtendBlock extends Block { 46 | data: SelectType | string; 47 | } 48 | interface Blocks { 49 | [key: string]: ExtendBlock; 50 | } 51 | 52 | declare global { 53 | module "blockly" { 54 | export * from "blockly/core/blockly"; 55 | const Blocks: Blocks 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/interface/http.ts: -------------------------------------------------------------------------------- 1 | import { AxiosError, AxiosPromise, AxiosRequestConfig, AxiosResponse } from "axios"; 2 | import { instanceObject } from "@/utils/format"; 3 | 4 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 5 | export interface IRequestConfig extends AxiosRequestConfig { 6 | // 当网络请求错误时是否显示错误 7 | showResponseError?: boolean; 8 | // 当http 200但是 serverResponse.code !== 200 时是否显示 serverResponse.message 9 | // 默认开启 10 | showServerResponseError?: boolean; 11 | // 返回值是否是文件流 12 | isBlob?: boolean; 13 | version?: "v1" | "v2"; 14 | } 15 | 16 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 17 | export interface IResponseError extends AxiosError { 18 | config: IRequestConfig; 19 | } 20 | 21 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 22 | export interface IResponse extends AxiosResponse { 23 | config: IRequestConfig; 24 | } 25 | export interface ServerResponse { 26 | code: number; 27 | message: string; 28 | data: T; 29 | } 30 | export interface ApiServiceAdapter { 31 | upload(url: string, file: FormData | File): Promise>; 32 | download(id: string): AxiosPromise; 33 | raw(config: IRequestConfig): Promise>; 34 | urlDownload(url: string, data: instanceObject): void; 35 | } 36 | 37 | export const NetworkAdapter = { 38 | Offline: "离线", 39 | Localhost: "本地连接", 40 | Proxy: "代理", 41 | }; 42 | export type NetworkAdapterType = keyof typeof NetworkAdapter; 43 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/interface/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./modules/config"; 2 | export type Config2Map = { 3 | [key in keyof Config]: { 4 | value: Config[key]; 5 | description: string; 6 | }; 7 | }; 8 | 9 | export type Config2Form = { 10 | [key in keyof Config]: Config[key] | null; 11 | }; 12 | 13 | export function enumTypeList(list: T) { 14 | return Object.keys(list).map((key) => ({ 15 | label: Reflect.get(list, key), 16 | value: key, 17 | })); 18 | } 19 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/interface/modules/blockly.ts: -------------------------------------------------------------------------------- 1 | export interface BlocklyProject { 2 | name: string; 3 | uuid: string | null; 4 | blocklyProject: string | BlocklyProjectWorkspace; 5 | userData: string; 6 | } 7 | 8 | export interface BlocklyProjectWorkspace { 9 | [key: string]: string; 10 | } 11 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/interface/modules/config.ts: -------------------------------------------------------------------------------- 1 | export interface BotGroupConfig { 2 | bot: number; 3 | groups: number[]; 4 | } 5 | 6 | export interface ServerAronaConfig { 7 | [key: string]: unknown; 8 | } 9 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/interface/modules/contact.ts: -------------------------------------------------------------------------------- 1 | import { Friend, Group, Member } from "@/types/contact"; 2 | 3 | export interface ExtendGroup extends Group { 4 | member: Member[]; 5 | } 6 | 7 | export interface BotContact { 8 | bot: number; 9 | groups: ExtendGroup[]; 10 | friends: Friend[]; 11 | } 12 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/interface/modules/db.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/prefer-default-export 2 | export const enum AvailableDB { 3 | GachaPools = "GachaPools", 4 | GachaPoolCharacters = "GachaPoolCharacters", 5 | GachaCharacters = "GachaCharacters", 6 | } 7 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/interface/modules/gacha.ts: -------------------------------------------------------------------------------- 1 | export interface GachaCharacter { 2 | id: number; 3 | name: string; 4 | star: number; 5 | limit: boolean; 6 | } 7 | 8 | export interface GachaPool { 9 | id: number; 10 | name: string; 11 | characters: GachaCharacter[]; 12 | } -------------------------------------------------------------------------------- /arona-webui-frontend/src/interface/modules/reply.ts: -------------------------------------------------------------------------------- 1 | import { enumTypeList } from "@/interface"; 2 | 3 | const DReplyItemType = { 4 | Image: "图片", 5 | String: "文字", 6 | }; 7 | 8 | export const ReplyItemTypeList = enumTypeList(DReplyItemType); 9 | 10 | export type ReplyItemType = keyof typeof DReplyItemType; 11 | export interface ReplyItem { 12 | type: ReplyItemType; 13 | content: string; 14 | } 15 | 16 | /** 17 | * 一个回复的最小单位 18 | */ 19 | export interface ReplyGroup { 20 | id: number; // 数据库主键 21 | content: ReplyItem[]; // 内容, 可以是单个句子, 也可以是句子与图片组合, 目前只支持句子 22 | weight: number; // 内容权重, 内容最终权重 = 句子权重 + 标签权重 23 | label: number[]; // 所属标签 24 | } 25 | 26 | /** 27 | * 标签定义 28 | */ 29 | export interface ReplyLabel { 30 | id: number; // 数据库主键 31 | value: string; // 标签内容 32 | weight: number; // 标签权重, 内容最终权重 = 句子权重 + 标签权重 33 | } 34 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/interface/modules/setting.ts: -------------------------------------------------------------------------------- 1 | import { Config2Form } from ".."; 2 | 3 | export interface APISetting { 4 | host: string; 5 | port: number; 6 | } 7 | 8 | export type APISettingForm = Config2Form; 9 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/main.ts: -------------------------------------------------------------------------------- 1 | // i18n 2 | import { createI18n } from "vue-i18n"; 3 | import messages from "@intlify/vite-plugin-vue-i18n/messages"; 4 | // vue router 5 | import router from "@/router/index"; 6 | // pinia 7 | import store from "@/store"; 8 | import App from "./App.vue"; 9 | 10 | import "virtual:windi.css"; 11 | // Devtools: https://windicss.org/integrations/vite.html#design-in-devtools 12 | import "virtual:windi-devtools"; 13 | import "@/assets/styles/index.scss"; 14 | import "element-plus/dist/index.css"; 15 | import { setApp } from "@/utils/vueTools"; 16 | 17 | const i18n = createI18n({ 18 | locale: "zh-cn", 19 | fallbackLocale: "zh", 20 | messages, 21 | }); 22 | 23 | const app = createApp(App); 24 | 25 | app.use(router).use(store); 26 | 27 | app.use(i18n); 28 | 29 | app.mount("#app"); 30 | 31 | setApp(app); 32 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/router/config/config/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from "vue-router"; 2 | 3 | const ConfigRouter: Array = [ 4 | { 5 | path: "config", 6 | meta: { 7 | title: "配置文件", 8 | }, 9 | component: () => import("@/components/SubPageIndex.vue"), 10 | children: [ 11 | { 12 | path: "", 13 | redirect: "config-arona-blockly", 14 | }, 15 | { 16 | path: "config-arona-blockly", 17 | name: "config-arona-blockly", 18 | meta: { 19 | title: "条件执行配置文件", 20 | }, 21 | component: () => import("@/views/config/config/ConfigAronaBlockly.vue"), 22 | }, 23 | { 24 | path: "config-arona-main", 25 | name: "config-arona-main", 26 | meta: { 27 | title: "主配置文件", 28 | }, 29 | component: () => import("@/views/config/config/ConfigAronaMain.vue"), 30 | }, 31 | { 32 | path: "config-arona-reply-group", 33 | name: "config-arona-reply-group", 34 | meta: { 35 | title: "随机回复语句", 36 | }, 37 | component: () => import("@/views/config/config/ConfigRandomReply.vue"), 38 | }, 39 | { 40 | path: "config-arona-reply-label", 41 | name: "config-arona-reply-label", 42 | meta: { 43 | title: "随机回复标签", 44 | }, 45 | component: () => import("@/views/config/config/ConfigRandomReplyLabel.vue"), 46 | }, 47 | ], 48 | }, 49 | ]; 50 | export default ConfigRouter; 51 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/router/config/database/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from "vue-router"; 2 | 3 | const DatabaseRouter: Array = [ 4 | { 5 | path: "database", 6 | meta: { 7 | title: "数据库", 8 | }, 9 | component: () => import("@/components/SubPageIndex.vue"), 10 | children: [ 11 | { 12 | path: "", 13 | redirect: "database-gacha-pool", 14 | }, 15 | { 16 | path: "database-gacha-pool", 17 | name: "database-gacha-pool", 18 | meta: { 19 | title: "卡池信息数据库", 20 | }, 21 | component: () => import("@/views/config/database/DatabaseGachaPool.vue"), 22 | }, 23 | { 24 | path: "database-gacha-history", 25 | name: "database-gacha-history", 26 | meta: { 27 | title: "抽卡记录数据库", 28 | }, 29 | component: () => import("@/views/config/database/DatabaseGachaHistory.vue"), 30 | }, 31 | ], 32 | }, 33 | ]; 34 | export default DatabaseRouter; 35 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/router/config/index.ts: -------------------------------------------------------------------------------- 1 | // 需要鉴权的业务路由 2 | import { RouteRecordRaw } from "vue-router"; 3 | import ConfigMenu from "@/router/config/config"; 4 | import DatabaseMenu from "@/router/config/database"; 5 | import SettingRouter from "@/router/config/setting"; 6 | 7 | const ConfigRoutes: Array = [ 8 | { 9 | path: "/config", 10 | name: "config-index", 11 | redirect: "/config/home", 12 | meta: { 13 | title: "", 14 | icon: "", 15 | }, 16 | component: () => import("@/views/config/ConfigIndex.vue"), 17 | children: [ 18 | { 19 | path: "/config/home", 20 | name: "config-home", 21 | meta: { 22 | title: "", 23 | icon: "", 24 | }, 25 | component: () => import("@/views/config/home/ConfigHome.vue"), 26 | }, 27 | ...ConfigMenu, 28 | ...DatabaseMenu, 29 | ...SettingRouter, 30 | ], 31 | }, 32 | ]; 33 | 34 | export default ConfigRoutes; 35 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/router/config/setting/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from "vue-router"; 2 | 3 | const SettingRouter: Array = [ 4 | { 5 | path: "setting", 6 | meta: { 7 | title: "设置", 8 | }, 9 | component: () => import("@/components/SubPageIndex.vue"), 10 | children: [ 11 | { 12 | path: "", 13 | redirect: "setting-api", 14 | }, 15 | { 16 | path: "setting-api", 17 | name: "setting-api", 18 | meta: { 19 | title: "api设置", 20 | }, 21 | component: () => import("@/views/config/setting/SettingAPI.vue"), 22 | }, 23 | ], 24 | }, 25 | ]; 26 | export default SettingRouter; 27 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory, Router, RouteRecordRaw } from "vue-router"; 2 | import NProgress from "nprogress"; 3 | import exceptionRoutes from "@/router/route.exception"; 4 | import asyncRoutes from "@/router/route.async"; 5 | import commonRoutes from "@/router/route.common"; 6 | 7 | const routes: Array = [ 8 | // 无鉴权的业务路由 ex:登录 9 | ...commonRoutes, 10 | // 带鉴权的业务路由 11 | ...asyncRoutes, 12 | // 异常页必须放在路由匹配规则的最后 13 | ...exceptionRoutes, 14 | ]; 15 | 16 | const router: Router = createRouter({ 17 | // 新的vue-router4 使用 history路由模式 和 base前缀 18 | history: createWebHistory(import.meta.env.VITE_BASE), 19 | routes, 20 | }); 21 | 22 | /** 23 | * @description: 全局路由前置守卫,在进入路由前触发,导航在所有守卫 resolve 完之前一直处于等待中。 24 | * @param { RouteLocationNormalized } to 即将要进入的目标 25 | * @param { RouteLocationNormalizedLoaded } from 当前导航正在离开的路由 26 | * @return {*} 27 | */ 28 | router.beforeEach((to, from) => { 29 | // console.log("全局路由前置守卫:to,from\n", to, from); 30 | // 设置页面标题 31 | document.title = (to.meta.title as string) || import.meta.env.VITE_APP_TITLE; 32 | if (!NProgress.isStarted()) { 33 | NProgress.start(); 34 | } 35 | }); 36 | 37 | router.afterEach((to, from) => { 38 | // console.log("全局路由后置守卫:to,from\n", to, from); 39 | NProgress.done(); 40 | }); 41 | 42 | export default router; 43 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/router/route.async.ts: -------------------------------------------------------------------------------- 1 | // 需要鉴权的业务路由 2 | import { RouteRecordRaw } from "vue-router"; 3 | import ConfigRoutes from "@/router/config"; 4 | 5 | const asyncRoutes: Array = [ 6 | { 7 | path: "/", 8 | redirect: "/home", 9 | }, 10 | { 11 | path: "/home", 12 | name: "home", 13 | meta: { 14 | title: "", 15 | icon: "", 16 | }, 17 | component: () => import("@/views/home/HomeIndex.vue"), 18 | }, 19 | ...ConfigRoutes, 20 | ]; 21 | 22 | export default asyncRoutes; 23 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/router/route.common.ts: -------------------------------------------------------------------------------- 1 | // 不需要鉴权的业务路由 2 | import { RouteRecordRaw } from "vue-router"; 3 | 4 | const commonRoutes: Array = []; 5 | 6 | export default commonRoutes; 7 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/router/route.exception.ts: -------------------------------------------------------------------------------- 1 | // 跟鉴权无关的特殊路由 2 | import { RouteRecordRaw } from "vue-router"; 3 | 4 | const exceptionRoutes: Array = [ 5 | { 6 | path: "/401", 7 | name: "401", 8 | meta: { 9 | title: "需要登录", 10 | }, 11 | component: () => import("@/views/config/exception/401.vue"), 12 | }, 13 | { 14 | path: "/404", 15 | name: "404", 16 | meta: { 17 | title: "非常抱歉,页面走丢了", 18 | }, 19 | component: () => import("@/views/config/exception/404.vue"), 20 | }, 21 | { 22 | path: "/:pathMatch(.*)", 23 | meta: {}, 24 | redirect: "/404", 25 | }, 26 | ]; 27 | 28 | export default exceptionRoutes; 29 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from "pinia"; 2 | import piniaPluginPersistedstate from "pinia-plugin-persistedstate"; 3 | 4 | const store = createPinia(); 5 | store.use(piniaPluginPersistedstate); 6 | 7 | export default store; 8 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/store/setting.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from "pinia"; 2 | import { SettingStoreState } from "./type"; 3 | import { NetworkAdapterType } from "@/interface/http"; 4 | import { updateAPIService } from "@/api/adapter/localhost"; 5 | 6 | const useSettingStore = defineStore({ 7 | id: "setting", 8 | state: (): SettingStoreState => ({ 9 | adapter: "Localhost", 10 | theme: { 11 | themeType: "亮蓝色", 12 | themeColor: "#2080F0FF", 13 | }, 14 | api: { 15 | host: undefined, 16 | port: undefined, 17 | }, 18 | }), 19 | getters: { 20 | getThemeType: (state: SettingStoreState) => state.theme.themeType, 21 | getThemeColor: (state: SettingStoreState) => state.theme.themeColor, 22 | isRestoreBackend: (state: SettingStoreState) => state.api.host && state.api.port, 23 | }, 24 | actions: { 25 | setAdapter(adapter: NetworkAdapterType) { 26 | this.adapter = adapter; 27 | }, 28 | setThemeType(type: string) { 29 | this.theme.themeType = type; 30 | }, 31 | saveAPISetting(host: string, port: number) { 32 | this.api.host = host; 33 | this.api.port = port; 34 | }, 35 | }, 36 | persist: { 37 | key: "setting", 38 | afterRestore: (ctx) => { 39 | if (ctx.store.isRestoreBackend) { 40 | updateAPIService(ctx.store.api.host, ctx.store.api.port); 41 | } 42 | }, 43 | }, 44 | }); 45 | 46 | export default useSettingStore; 47 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/store/type.ts: -------------------------------------------------------------------------------- 1 | import { ServerAronaConfig } from "@/interface"; 2 | import { BotContact } from "@/interface/modules/contact"; 3 | import { NetworkAdapterType } from "@/interface/http"; 4 | 5 | export interface BaseStoreState { 6 | config: ServerAronaConfig; // 配置文件大全 7 | activeGroupId: number; // 当前配置文件指向的group配置 8 | contactList: BotContact[]; // 所有arona能访问到的联系人信息 9 | } 10 | 11 | export interface SettingStoreState { 12 | adapter: NetworkAdapterType; 13 | theme: { 14 | themeType: string; 15 | themeColor: string | number; 16 | }; 17 | api: { 18 | host?: string; 19 | port?: number; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/types/api/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * API 请求格式 3 | * @packageDocumentation 4 | */ 5 | 6 | export * as Params from './params' 7 | export * as Response from './response' 8 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/types/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 群设置与成员信息设置 3 | * @packageDocumentation 4 | */ 5 | 6 | /** 7 | * 群设置 8 | */ 9 | export interface GroupConfig { 10 | /** 11 | * 群名 12 | */ 13 | name?: string; 14 | /** 15 | * 群公告 16 | */ 17 | announcement?: string; 18 | /** 19 | * 是否开启坦白说 20 | */ 21 | confessTalk?: boolean; 22 | /** 23 | * 是否允许群员邀请 24 | */ 25 | allowMemberInvite?: boolean; 26 | /** 27 | * 是否开启自动审批入群 28 | */ 29 | autoApprove?: boolean; 30 | /** 31 | * 是否允许匿名聊天 32 | */ 33 | anonymousChat?: boolean; 34 | } 35 | 36 | /** 37 | * 群员信息 38 | */ 39 | export interface MemberInfo { 40 | /** 41 | * 群名片 42 | */ 43 | name?: string; 44 | /** 45 | * 群头衔 46 | */ 47 | specialTitle?: string; 48 | } 49 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/types/contact.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 联系实体类型,参考 [mirai-core 命名](https://github.com/mamoe/mirai/tree/master/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact) 3 | * @packageDocumentation 4 | */ 5 | 6 | export type Permission = "OWNER" | "ADMINISTRATOR" | "MEMBER"; 7 | 8 | /** 9 | * 群的信息 10 | */ 11 | export interface Group { 12 | /** 13 | * 群号 14 | */ 15 | id: number; 16 | /** 17 | * 群的群名称 18 | */ 19 | name: string; 20 | /** 21 | * 群中,Bot的群限权 22 | */ 23 | permission: Permission; 24 | } 25 | 26 | /** 27 | * 基础用户信息 28 | */ 29 | interface BaseUser { 30 | /** 31 | * QQ 号 32 | */ 33 | id: number; 34 | } 35 | 36 | /** 37 | * 好友信息类型 38 | */ 39 | export interface Friend extends BaseUser { 40 | /** 41 | * 用户昵称 42 | */ 43 | name: string; 44 | /** 45 | * 用户备注 46 | */ 47 | remark: string; 48 | } 49 | 50 | /** 51 | * 群成员信息类型 52 | */ 53 | export interface Member extends BaseUser { 54 | /** 55 | * 群名片 56 | */ 57 | memberName: string; 58 | /** 59 | * 群权限 OWNER、ADMINISTRATOR 或 MEMBER 60 | */ 61 | permission: Permission; 62 | /** 63 | * 群头衔 64 | */ 65 | specialTitle: string; 66 | /** 67 | * 入群时间戳 68 | */ 69 | joinTimestamp: number; 70 | /** 71 | * 上一次发言时间戳 72 | */ 73 | lastSpeakTimestamp: number; 74 | /** 75 | * 剩余禁言时间 76 | */ 77 | muteTimeRemaining: number; 78 | /** 79 | * 所在的群 80 | */ 81 | group: Group; 82 | } 83 | 84 | export type User = Friend | Member; 85 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/types/index.ts: -------------------------------------------------------------------------------- 1 | // 从https://github.com/YunYouJun/mirai-ts扣过来的类型声明 2 | 3 | export * from "./setting"; 4 | 5 | export * from "./profile"; 6 | 7 | export * as Api from "./api"; 8 | export * as Config from "./config"; 9 | export * as Contact from "./contact"; 10 | export { MessageType } from "./message-type"; 11 | export * as EventType from "./event-type"; 12 | 13 | /** 14 | * mirai-ts 自定义配置项,与 mirai-api-http setting 相区别 15 | */ 16 | export interface MiraiOptions { 17 | http?: { 18 | address?: string; 19 | }; 20 | ws?: { 21 | address?: string; 22 | /** 23 | * 心跳间隔 24 | * @default 60000 25 | */ 26 | heartbeatInterval?: number; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/types/profile.ts: -------------------------------------------------------------------------------- 1 | export enum Sex { 2 | UNKNOWN = 'UNKNOWN', 3 | MALE = 'MALE', 4 | FEMALE = 'FEMALE', 5 | } 6 | 7 | export interface UserProfile { 8 | nickname: string 9 | email: string 10 | age: number 11 | level: number 12 | /** 13 | * mirai ? 14 | */ 15 | sign: string 16 | sex: Sex 17 | } 18 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/utils/config.ts: -------------------------------------------------------------------------------- 1 | import useBaseStore from "@/store/base"; 2 | import { BotGroupConfig } from "@/interface"; 3 | 4 | const GlobalConfigProvider = { 5 | get(key: string): T { 6 | const baseStore = useBaseStore(); 7 | return baseStore.getConfig(key); 8 | }, 9 | getGroup(key: string, group?: number): T { 10 | const baseStore = useBaseStore(); 11 | if (!group) { 12 | group = baseStore.activeGroupId; 13 | } 14 | return this.get(this.concatGroupKey(key, group)); 15 | }, 16 | getBotConfig(): BotGroupConfig[] { 17 | const baseStore = useBaseStore(); 18 | return baseStore.getConfig("bots"); 19 | }, 20 | concatGroupKey(key: string, group: number): string { 21 | return !group || group === 0 ? key : `${group}.${key}`; 22 | }, 23 | }; 24 | 25 | export default GlobalConfigProvider; 26 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/utils/config/emitter.ts: -------------------------------------------------------------------------------- 1 | import mitt from "mitt"; 2 | import useBaseStore from "@/store/base"; 3 | 4 | type Events = { 5 | "api-update": undefined; 6 | }; 7 | 8 | const emitter = mitt(); 9 | 10 | export function initEventBus() { 11 | const baseStore = useBaseStore(); 12 | emitter.on("api-update", baseStore.fetchBotContact); 13 | emitter.on("api-update", baseStore.fetchConfig); 14 | } 15 | 16 | export default emitter; 17 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/utils/dark.ts: -------------------------------------------------------------------------------- 1 | export const isDark = useDark(); 2 | export const toggleDark = useToggle(isDark); 3 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/utils/format.ts: -------------------------------------------------------------------------------- 1 | export declare interface instanceObject { 2 | [key: string]: string; 3 | } 4 | 5 | /** 6 | * JSON转url参数 7 | * @param data Json格式数据 8 | * */ 9 | export const formatJsonToUrlParams = (data: instanceObject) => { 10 | return typeof data === "object" 11 | ? Object.keys(data) 12 | .map((key) => { 13 | return `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`; 14 | }) 15 | .join("&") 16 | : ""; 17 | }; 18 | 19 | export default formatJsonToUrlParams; 20 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/utils/message.ts: -------------------------------------------------------------------------------- 1 | import { ElMessage, ElMessageBox } from "element-plus"; 2 | import { 3 | ElMessageBoxOptions, 4 | MessageBoxData, 5 | } from "element-plus/es/components/message-box/src/message-box.type"; 6 | 7 | export function infoMessage(info: any) { 8 | return ElMessage.info(info); 9 | } 10 | export function successMessage(info: any) { 11 | return ElMessage.success(info); 12 | } 13 | export function warningMessage(info: any) { 14 | return ElMessage.warning(info); 15 | } 16 | export function errorMessage(info: any) { 17 | return ElMessage.error(info); 18 | } 19 | 20 | export function IPrompt(title: string, message: string, config?: ElMessageBoxOptions): Promise { 21 | return ElMessageBox.prompt(message, title, config); 22 | } 23 | 24 | export function IConfirm(title: string, message: string, config?: ElMessageBoxOptions) { 25 | return ElMessageBox.confirm(message, title, config); 26 | } 27 | 28 | export function IWarningConfirm(title: string, message: string, config?: ElMessageBoxOptions) { 29 | return IConfirm(title, message, { 30 | ...config, 31 | type: "warning", 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/utils/time.ts: -------------------------------------------------------------------------------- 1 | import dayjs from "dayjs"; 2 | 3 | /** 4 | * 获取格式化的当前时间 5 | * @param format 格式化字符串 6 | * return 格式化的当前时间 7 | */ 8 | // eslint-disable-next-line import/prefer-default-export 9 | export function nowTime(format = "yyyy-MM-dd HH:mm:ss"): string { 10 | return dayjs().format(format); 11 | } 12 | 13 | export function nowSecond(time: number): string { 14 | return dayjs().startOf("day").second(time).format("mm:ss"); 15 | } 16 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/utils/vueTools.ts: -------------------------------------------------------------------------------- 1 | import { App, createVNode, defineAsyncComponent, render } from "vue"; 2 | import { VNodeProps } from "@vue/runtime-core"; 3 | 4 | type NodeEventListener = { 5 | type: K; 6 | handler: (ev: HTMLElementEventMap[K]) => void; 7 | }; 8 | export function mountAsyncComponent( 9 | loader: Parameters[0], 10 | props?: (Record & VNodeProps) | null, 11 | hook?: NodeEventListener[], 12 | ): HTMLElement { 13 | const component = defineAsyncComponent(loader); 14 | const componentVNode = createVNode(component, props); 15 | componentVNode.appContext = _app._context; 16 | const container = document.createElement("div"); 17 | if (hook) { 18 | hook.forEach(it => container.addEventListener(it.type, it.handler)); 19 | } 20 | render(componentVNode, container); 21 | return container; 22 | } 23 | 24 | let _app: App; 25 | export function setApp(app: App) { 26 | _app = app; 27 | } 28 | export function useApp() { 29 | return _app; 30 | } 31 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/views/config/ConfigIndex.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 41 | 42 | 55 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/views/config/config/ConfigIndex.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/views/config/config/event/main.ts: -------------------------------------------------------------------------------- 1 | import mitt from "mitt"; 2 | import useBaseStore from "@/store/base"; 3 | import {Friend} from "@/types/contact"; 4 | 5 | type Events = { 6 | "contact-update": { 7 | uuid: string; 8 | value: number; 9 | }; 10 | "bot-list-update": Friend[]; 11 | }; 12 | 13 | const MainConfigEmitter = mitt(); 14 | // 保存drag实例和其对应的群号/机器人q号的关系 15 | const uuidMap = ref(new Map()); 16 | export const botList = ref([]); 17 | function updateContact(data: { uuid: string; value: number }) { 18 | if (data.value) { 19 | uuidMap.value.set(data.uuid, data.value); 20 | } else { 21 | uuidMap.value.delete(data.uuid); 22 | } 23 | } 24 | function updateBotList(data: Friend[]) { 25 | botList.value = data; 26 | } 27 | MainConfigEmitter.on("contact-update", updateContact); 28 | MainConfigEmitter.on("bot-list-update", updateBotList); 29 | 30 | export const groupList = computed(() => { 31 | const baseStore = useBaseStore(); 32 | return baseStore.groups(); 33 | }); 34 | export const uuidMapEntries = computed(() => [...uuidMap.value.entries()]); 35 | 36 | export default MainConfigEmitter; 37 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/views/config/database/DatabaseGachaHistory.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/views/config/database/DatabaseGachaPool.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/views/config/database/DatabaseIndex.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/views/config/exception/401.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/views/config/exception/404.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/views/config/home/ConfigHome.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/views/config/setting/SettingIndex.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /arona-webui-frontend/src/views/config/tools/ToolIndex.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /arona-webui-frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "useDefineForClassFields": true, 5 | "module": "esnext", 6 | "moduleResolution": "node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "esModuleInterop": true, 12 | "lib": ["esnext", "dom"], 13 | "types": ["@intlify/vite-plugin-vue-i18n/client"], 14 | // baseUrl来告诉编译器到哪里去查找模块,所有非相对模块导入都会被当做相对于 baseUrl。 15 | "baseUrl": ".", 16 | // 非相对模块导入的路径映射配置 17 | "paths": { 18 | "@/*": ["src/*"], 19 | } 20 | }, 21 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "mock/index.d.ts"], 22 | // 编译器默认排除的编译文件 23 | "exclude": ["node_modules"], 24 | // ts-node 特殊编译选项 25 | "ts-node": { 26 | "compilerOptions": { 27 | "target": "es2020", 28 | "experimentalDecorators": true, 29 | "emitDecoratorMetadata": true, 30 | "useDefineForClassFields": true, 31 | "forceConsistentCasingInFileNames": true, 32 | "module": "CommonJS" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /arona-webui-frontend/windi.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite-plugin-windicss"; 2 | import typography from "windicss/plugin/typography"; 3 | import colors from "windicss/colors"; 4 | 5 | export default defineConfig({ 6 | darkMode: "class", 7 | plugins: [typography()], 8 | theme: { 9 | fontFamily: { 10 | sans: ["Open Sans", "ui-sans-serif", "system-ui"], 11 | serif: ["Montserrat", "ui-serif", "Georgia"], 12 | mono: ["Fira Sans", "ui-monospace", "SFMono-Regular"], 13 | }, 14 | extend: { 15 | typography: { 16 | DEFAULT: { 17 | css: { 18 | maxWidth: "65ch", 19 | color: "inherit", 20 | a: { 21 | color: "inherit", 22 | opacity: 0.75, 23 | fontWeight: "500", 24 | textDecoration: "underline", 25 | "&:hover": { 26 | opacity: 1, 27 | color: colors.teal[600], 28 | }, 29 | }, 30 | b: { color: "inherit" }, 31 | strong: { color: "inherit" }, 32 | em: { color: "inherit" }, 33 | h1: { color: "inherit" }, 34 | h2: { color: "inherit" }, 35 | h3: { color: "inherit" }, 36 | h4: { color: "inherit" }, 37 | code: { color: "inherit" }, 38 | }, 39 | }, 40 | }, 41 | }, 42 | }, 43 | }); 44 | -------------------------------------------------------------------------------- /githook/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # An example hook script to verify what is about to be committed. 4 | # Called by "git commit" with no arguments. The hook should 5 | # exit with non-zero status after issuing an appropriate message if 6 | # it wants to stop the commit. 7 | # 8 | # To enable this hook, rename this file to "pre-commit". 9 | 10 | if git rev-parse --verify HEAD >/dev/null 2>&1 11 | then 12 | against=HEAD 13 | else 14 | # Initial commit: diff against an empty tree object 15 | against=$(git hash-object -t tree /dev/null) 16 | fi 17 | 18 | # Redirect output to stderr. 19 | exec 1>&2 20 | 21 | if test $(git diff --cached -z HEAD | grep -E "[+]\s*[A-Z_]+SECRET_(ID|KEY): ?\w+" | wc -c) != 0 22 | then 23 | cat <<\EOF 24 | Error: 你他妈忘记把密码删了, 啥b. 25 | EOF 26 | exit 1 27 | fi 28 | -------------------------------------------------------------------------------- /tools/.gitignore: -------------------------------------------------------------------------------- 1 | log.7z 2 | log/ 3 | log.db 4 | db/ -------------------------------------------------------------------------------- /tools/config.py: -------------------------------------------------------------------------------- 1 | cache_file_location = r"./config/student_cache.json" 2 | name_map_dict_file_location = r"./config/name_map_dict.txt" 3 | cn_translation_location = r"./config/translation_dict.json" 4 | 5 | if __name__ == "__main__": 6 | pass -------------------------------------------------------------------------------- /tools/config/error.txt: -------------------------------------------------------------------------------- 1 | 响(应援团) 应援团响 2 | 阿露(正月) 正月阿露 3 | 野宫 富婆 4 | 莲见(体操服) 运动服莲见 5 | 纱绫 沙耶 6 | 歌原(应援团) 应援团歌原 7 | 8 | skip: 阳奈, 78/118 1 9 | skip: 亚琉, 74/118 1 10 | skip: 麻白, 73/118 1 11 | skip: 初音, 45/118 1 12 | skip: 椿, 97/118 1 13 | 14 | 低分部错误信息 -------------------------------------------------------------------------------- /tools/config/group_download.yml: -------------------------------------------------------------------------------- 1 | image: 2 | - name: 'test' 3 | path: './image/some/' 4 | url: '' 5 | group: '' 6 | type: "vertical" # horizen or vertical 7 | source: '7' 8 | - name: 'test' 9 | path: './image/some/' 10 | url: '' 11 | source: '7' 12 | - name: 'test' 13 | path: './image/student_rank/' 14 | url: '' 15 | source: '7' -------------------------------------------------------------------------------- /tools/config/name_map_dict.txt: -------------------------------------------------------------------------------- 1 | 响(应援团),应援团响 2 | 阿露(正月),正月阿露 3 | 野宫,富婆 4 | 莲见(体操服),运动服莲见 5 | 纱绫,沙耶 6 | 歌原(应援团),应援团歌原 7 | 朱音,茜 8 | 朱音(兔女郎),茜(兔女郎) 9 | 明里,亚伽里 10 | 朱莉,茱莉 11 | 白子(单车),骑行白子 12 | 白子(骑行),骑行白子 13 | 巴,智惠 14 | 花江,花绘 15 | 花江(圣诞),花绘(圣诞) 16 | 春香,遥香 17 | 真希,真纪 18 | 菫,堇 19 | 芹奈,芹娜 20 | ハルナ(正月),正月羽留奈 21 | フウカ(正月),春枫香 22 | ジュンコ(正月),春纯子 23 | 晴奈(正月),正月羽留奈 24 | 枫香(正月),春枫香 25 | 淳子(正月),春纯子 26 | ミネ,美祢 27 | ノノミ(水着),泳装野乃美 28 | ミカ,未花 29 | カンナ,叶渚 30 | メグ,惠 31 | トキ,时 32 | ナギサ,渚 -------------------------------------------------------------------------------- /tools/fill_chara_with_simple.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | import os 3 | 4 | ## 将巴哈角色攻略图片插入数据库 5 | ## 已弃用 6 | 7 | file_path = r"C:\Users\qwe13\Desktop\data.db" 8 | name_and_code = r".\image\student_rank" 9 | def replace0(source): 10 | first = source.find("(") 11 | last = source.find(")") 12 | if first != -1: 13 | source = source[first+1: last] + source[0:first] 14 | return source 15 | if __name__ == '__main__': 16 | connection = sqlite3.connect(file_path) 17 | cursor = connection.cursor() 18 | index = 0 19 | print("数据库连接成功") 20 | for file in os.listdir(name_and_code): 21 | divs = file.replace(".png", "") 22 | names = divs.split("_") 23 | first_name = names[0] 24 | last_name = names[1] 25 | last_name = replace0(last_name) 26 | cursor.execute("INSERT INTO `student_rank_0`(`name`, `code`) VALUES ('%s', '%s')" % (last_name, file)) 27 | connection.commit() 28 | if len(names) > 2: 29 | alias = names[2: len(names)] 30 | cursor.execute("SELECT * FROM `student_rank_0` WHERE `code` = '%s'" % file) 31 | id = cursor.fetchone()[0] 32 | for a in alias: 33 | a = replace0(a) 34 | cursor.execute("INSERT INTO `student_rank_0`(`name`, `code`) VALUES ('%s', '%s')" % (a, id)) 35 | connection.commit() 36 | index += 1 37 | print("成功! %d" % index) -------------------------------------------------------------------------------- /tools/generate_game_db_overview.py: -------------------------------------------------------------------------------- 1 | import time 2 | from playwright.sync_api import Playwright, sync_playwright 3 | 4 | def run(playwright: Playwright): 5 | browser = playwright.chromium.launch(headless=True, slow_mo=100) 6 | context = browser.new_context(viewport={'width': 1920, 'height': 1950}, device_scale_factor=2.0) 7 | page = context.new_page() 8 | 9 | # 拿到成长资源截图 10 | page.goto("https://ba.game-db.tw/") 11 | page.locator("svg").first.click() 12 | page.locator("#react-select-2-option-0").click() 13 | page.locator("text=素材 >> nth=1").click() 14 | time.sleep(2) 15 | page.screenshot(path="./image/some/材料一览.png", type="png") 16 | page.close() 17 | context.close() 18 | browser.close() 19 | 20 | if __name__ == "__main__": 21 | with sync_playwright() as playwright: 22 | run(playwright) -------------------------------------------------------------------------------- /tools/playwright/fxxkPlaywwright.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | let set = localStorage.getItem("settings"); 3 | if (set) { 4 | set = JSON.parse(set); 5 | set.language = 'zh'; 6 | set.server = 0; 7 | } else { 8 | set = { language: 'zh', server: 0 } 9 | } 10 | localStorage.setItem("settings", JSON.stringify(set)); 11 | let sd = localStorage.getItem("studentDisplay"); 12 | if (sd) { 13 | sd = JSON.parse(sd); 14 | sd.WeaponLevelDisplay = 50; 15 | sd.BondLevelDisplay = 20; 16 | } else { 17 | sd = { WeaponLevelDisplay: 50, BondLevelDisplay: 20 } 18 | } 19 | localStorage.setItem("studentDisplay", JSON.stringify(sd)); 20 | window.setInterval(() => { 21 | const model = document.querySelectorAll(".show").length; 22 | if (model !== 0) { 23 | const btn = document.querySelector(".btn-close-white"); 24 | if (btn) { 25 | btn.click(); 26 | } 27 | } 28 | }, 1000); 29 | })(); -------------------------------------------------------------------------------- /tools/playwright/im/equipment_icon_charm_tier9.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/equipment_icon_charm_tier9.webp -------------------------------------------------------------------------------- /tools/playwright/im/equipment_icon_charm_tier9_piece.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/equipment_icon_charm_tier9_piece.webp -------------------------------------------------------------------------------- /tools/playwright/im/equipment_icon_necklace_tier9.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/equipment_icon_necklace_tier9.webp -------------------------------------------------------------------------------- /tools/playwright/im/equipment_icon_necklace_tier9_piece.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/equipment_icon_necklace_tier9_piece.webp -------------------------------------------------------------------------------- /tools/playwright/im/equipment_icon_watch_tier9.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/equipment_icon_watch_tier9.webp -------------------------------------------------------------------------------- /tools/playwright/im/equipment_icon_watch_tier9_piece.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/equipment_icon_watch_tier9_piece.webp -------------------------------------------------------------------------------- /tools/playwright/im/item_icon_material_exskill_highlander_0.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/item_icon_material_exskill_highlander_0.webp -------------------------------------------------------------------------------- /tools/playwright/im/item_icon_material_exskill_highlander_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/item_icon_material_exskill_highlander_1.webp -------------------------------------------------------------------------------- /tools/playwright/im/item_icon_material_exskill_highlander_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/item_icon_material_exskill_highlander_2.webp -------------------------------------------------------------------------------- /tools/playwright/im/item_icon_material_exskill_highlander_3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/item_icon_material_exskill_highlander_3.webp -------------------------------------------------------------------------------- /tools/playwright/im/item_icon_skillbook_highlander_0.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/item_icon_skillbook_highlander_0.webp -------------------------------------------------------------------------------- /tools/playwright/im/item_icon_skillbook_highlander_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/item_icon_skillbook_highlander_1.webp -------------------------------------------------------------------------------- /tools/playwright/im/item_icon_skillbook_highlander_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/item_icon_skillbook_highlander_2.webp -------------------------------------------------------------------------------- /tools/playwright/im/item_icon_skillbook_highlander_3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diyigemt/arona/1ebc1fed56f78bb570ab1f6a725b8fc943ee5851/tools/playwright/im/item_icon_skillbook_highlander_3.webp -------------------------------------------------------------------------------- /tools/requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4 2 | numpy 3 | paramiko 4 | Pillow 5 | playwright 6 | PyYAML 7 | cos-python-sdk-v5 8 | Requests 9 | zhconv 10 | zhon 11 | opencv-python 12 | tencentcloud-sdk-python-common==3.0.754 -------------------------------------------------------------------------------- /tools/test_playwright.py: -------------------------------------------------------------------------------- 1 | from playwright.sync_api import Playwright, sync_playwright, Route, Request 2 | 3 | def content_override(route: Route, req: Request): 4 | route.fulfill(path="playwright/fake.js") 5 | pass 6 | 7 | def run(playwright: Playwright): 8 | browser = playwright.chromium.launch( 9 | proxy={"server":"http://127.0.0.1:7890"}, 10 | headless=False, 11 | chromium_sandbox=False, 12 | args=[r"--disk-cache-dir=D:\tmp\playwright"], 13 | slow_mo=100 14 | ) 15 | context = browser.new_context(viewport={'width': 1920, 'height': 1080}) 16 | context.set_extra_http_headers({"Cache-Control": "max-age=3600"}) 17 | page = context.new_page() 18 | page.add_init_script(path="playwright/init.js") 19 | page.route("https://ba.game-db.tw/static/main.276d869eba0ea14c09b6.js", content_override) 20 | page.goto("https://ba.game-db.tw/") 21 | page.wait_for_load_state() 22 | page.locator("svg").first.click() 23 | page.locator("#react-select-2-option-0").click() 24 | page.get_by_text("一覧").click() 25 | page.pause() 26 | print(1) 27 | print(2) 28 | 29 | 30 | if __name__ == "__main__": 31 | with sync_playwright() as playwright: 32 | run(playwright) -------------------------------------------------------------------------------- /tools/update_main_map.py: -------------------------------------------------------------------------------- 1 | from tools import post_data, post_image_to_remote, update_image_from_api 2 | base_folder = "/chapter_map/" 3 | 4 | # 更新main_map图片文件夹下的图片 5 | 6 | if __name__ == '__main__': 7 | image_dict = update_image_from_api(base_folder, type=2) 8 | post_image_to_remote(base_folder) 9 | post_data("imageUpdate", image_dict) 10 | -------------------------------------------------------------------------------- /tools/update_some.py: -------------------------------------------------------------------------------- 1 | from tools import post_data, post_image_to_remote, update_image, update_image_from_api 2 | 3 | base_folder = "/some/" 4 | 5 | # 更新杂图 6 | # tencentcloud-sdk-python-common==3.0.754 7 | 8 | if __name__ == '__main__': 9 | image_dict = update_image_from_api(base_folder, type=3) 10 | post_image_to_remote(base_folder) 11 | post_data("imageUpdate", image_dict) --------------------------------------------------------------------------------