diff --git a/build.gradle b/build.gradle index 1ba1412..aff5df9 100644 --- a/build.gradle +++ b/build.gradle @@ -64,7 +64,6 @@ if (project.hasProperty("publishMvnRepoUrl")) { group proj_group version proj_version_full -setArchivesBaseName proj_archive_name repositories { mavenCentral() @@ -75,7 +74,8 @@ dependencies { compileOnlyApi "com.github.spotbugs:spotbugs-annotations:${lib_spotbugs_v}" - api "cc.sukazyo:messiva:${lib_messiva_v}" + implementation "cc.sukazyo:messiva:${lib_messiva_v}" + implementation "cc.sukazyo:resource-tools:${lib_resourcetools_v}" implementation "com.github.pengrad:java-telegram-bot-api:${lib_javatelegramapi_v}" implementation "com.squareup.okhttp3:okhttp:${lib_okhttp_v}" @@ -139,6 +139,7 @@ buildConfig { shadowJar { + archiveBaseName.set proj_archive_name archiveClassifier.set "fat" if (project.hasProperty("dockerBuild")) { diff --git a/gradle.properties b/gradle.properties index 24b3c02..2996049 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ MORNY_ARCHIVE_NAME = morny-coeur MORNY_CODE_STORE = https://github.com/Eyre-S/Coeur-Morny-Cono MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s -VERSION = 1.0.0-RC3.9 +VERSION = 1.0.0-RC4 USE_DELTA = false VERSION_DELTA = @@ -17,6 +17,7 @@ CODENAME = beiping lib_spotbugs_v = 4.7.3 lib_messiva_v = 0.1.1 +lib_resourcetools_v = 0.2.2 lib_javatelegramapi_v = 6.2.0 diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyAbout.java b/src/main/java/cc/sukazyo/cono/morny/MornyAbout.java new file mode 100644 index 0000000..3933d9b --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/MornyAbout.java @@ -0,0 +1,31 @@ +package cc.sukazyo.cono.morny; + +import java.io.IOException; + +/** + * Some of the static information of Morny. + */ +public class MornyAbout { + + /** + * ASCII art of Morny Featured Image. + *

+ * used for Coeur starting welcome screen. + *

+ * stored at /assets_morny/texts/server-hello.txt + */ + public static final String MORNY_PREVIEW_IMAGE_ASCII; + static { + try { + MORNY_PREVIEW_IMAGE_ASCII = MornyAssets.pack.getResource("texts/server-hello.txt").readAsString(); + } catch (IOException e) { + throw new RuntimeException("Cannot read MORNY_PREVIEW_IMAGE_ASCII from assets pack", e); + } + } + + public static final String MORNY_SOURCECODE_LINK = "https://github.com/Eyre-S/Coeur-Morny-Cono"; + public static final String MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK = "https://storage.sukazyo.cc/Eyre_S/Coeur-Morny-Cono"; + public static final String MORNY_ISSUE_TRACKER_LINK = "https://github.com/Eyre-S/Coeur-Morny-Cono/issues"; + public static final String MORNY_USER_GUIDE_LINK = "https://book.sukazyo.cc/morny"; + +} diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyAssets.java b/src/main/java/cc/sukazyo/cono/morny/MornyAssets.java new file mode 100644 index 0000000..1fdfe7f --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/MornyAssets.java @@ -0,0 +1,19 @@ +package cc.sukazyo.cono.morny; + +import cc.sukazyo.restools.ResourcesPackage; + +/** + * Morny assets manager. + * + * @see #pack + * @since 1.0.0-RC4 + */ +public class MornyAssets { + + /** + * Instance mirror of the Morny assets, the assets root is /src/main/resources/assets_morny/. + * @since 1.0.0-RC4 + */ + public static final ResourcesPackage pack = new ResourcesPackage(MornyAssets.class, "assets_morny"); + +} diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyHello.java b/src/main/java/cc/sukazyo/cono/morny/MornyHello.java deleted file mode 100644 index 8a3725b..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/MornyHello.java +++ /dev/null @@ -1,70 +0,0 @@ -package cc.sukazyo.cono.morny; - -/** - * {@link #MORNY_PREVIEW_IMAGE_ASCII} 静态数据存放类 - */ -@SuppressWarnings("all") -public class MornyHello { - - /** - * 系统的开屏欢迎语 ASCII 字符画字段 - */ - public static final String MORNY_PREVIEW_IMAGE_ASCII = """ - ttt///t/////fucj(\\tvnxtf{< .' .. .:i` . . ^!`l|-^i+,!_[:1/|{i?//\\//jf\\\\\\///\\\\\\\\//\\\\\\//////\\\\/\\\\\\\\\\\\\\\\\\\\\\\\\\\\//\\\\\\\\/\\\\\\\\/\\\\//\\\\\\///\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\fnncvvU0O00QCx!!". .. ` \s - tt//////////\\jzjrucnjt/?{j,,"' . .' .. .":. .;{: ' "`.,1(<."i?)\\(-}\\\\\\(((\\\\/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\///\\//////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\|\\\\\\\\\\\\///\\\\///\\\\\\\\\\\\\\\\|\\\\\\\\\\\\|\\\\\\\\\\\\\\\\tvXvuXcxn/[Il)({_:.. ."` .,\s - //////////////////\\////|)/([}-_<+[]>.^^""[<'`^` .''""`'.`'`"i! ^!>l:' :<" !!.IiI`+l^^`i>_<`??)1;^{\\\\\\\\\\{|({({|/\\]I)\\\\()\\(]}|\\\\||\\|||\\/\\\\\\\\\\\\|||\\\\\\\\\\\\\\\\//\\\\\\\\/\\\\\\\\||\\\\\\\\\\\\\\\\//\\\\\\\\\\\\\\\\\\\\\\/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\//\\\\\\\\\\\\\\\\\\\\\\\\////\\\\\\\\\\\\\\\\\\//|{{?{|)[[-; - ttt/tt//////////////////{)(\\t(/tt/1~I}{-1\\_^])1_+[{|(?"<1~>>+!+[}11)}[(1}]};^1\\|~_1}{I:-1(I+)(|))|\\\\/////////\\\\////\\\\\\/////\\\\\\\\\\\\\\\\\\\\\\\\\\\\/\\//\\\\///\\//||\\////|)(//\\\\///){\\/\\(11|///({)//({[1\\\\\\\\\\\\\\\\\\\\|\\/\\\\\\/\\//////////\\\\\\\\\\\\\\\\\\//\\\\\\\\\\///////\\|\\\\\\\\//////\\\\///\\ - tttt/////////////\\///////\\||///////t//|(|)|}|\\/(\\\\(//(l_{{. ... ">+<^'I!: ^<(\\\\1}1//\\\\\\//////////\\\\///\\/\\///\\\\\\\\\\\\//\\\\//\\\\\\\\\\\\\\\\\\\\\\\\\\\\///\\(/\\{ - t////////////////////////////////////////////////////////\\/\\\\///////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/\\\\\\\\\\\\||\\|\\\\\\\\\\|\\\\\\\\/\\\\|\\\\\\\\\\\\////((|///}!:,":,^`. .;' ' '^..':. ^!;. .^^ '^^`. '' ...I[{!>:^;_i:'~\\ttt/////tt//\\\\////////////\\\\\\\\/\\\\\\\\\\\\/\\\\\\\\/\\\\\\\\\\)}-+[+I??i - ttt////////////////////////////////////////////////////////\\\\//\\//\\\\/\\\\\\\\\\\\\\\\\\\\//\\\\\\\\\\\\||\\\\\\/\\//\\\\\\\\\\\\\\\\\\/\\|\\\\\\////\\1;``^;<>+!">__+I `' .. "'. .;" ;;. .:^ ``,,;'` .;]I ,-_-|\\////t////t///////\\/\\\\\\\\//\\\\\\\\\\\\//\\\\\\///////-II1ttt///tttt/////////\\/\\/////\\\\\\\\////t|+<}?!-]l<{[[1-+] - t//////////////////////////////////////\\/////////\\////////////////\\//////\\//tttttttttt//////////////////////////)_)t)|}1f/{<.^,^:~: . .. '''^:-|/> '-/}-_?\\/)-{?(//\\(\\tt////\\///\\\\\\\\\\\\\\///t1.;); .l~` '" - ///////////////////////////////////////////tt/t(|tt//]+{t\\{][|////\\//////////ttttt///t//t/////////////\\//////|//{[|f}!l>~++~<<\\//]l~?])tt//\\\\\\\\\\/\\\\///\\\\|?<_}["^!;I^;]:. . - ////////////////////////////////tttt/|{[1)]~!!+>!<_(/|[-<"i!l,]tt//ttt/t////ttt//t///ttttttt////////t//t//ttt){+. :?^ '. l_-!+l;;;|!!>~~il!lllllllllll!!lI:`'. .' :I;]_}>,?tf:.+fft)l+1//\\~`'I-(//\\/t/|/(-1[)/?>>II:' '.`';-'` \s - /////////////////////////t//()\\1_<>il^'''' ,!>;.,.'{tti `~tf(`'-(|fffftttttttttt/tttttttttttt///tttft//(t|]?-+!^ ."`. `. ;!I,. .?{il-\\_!~<>>!lII;IllIIIIIllllllllllI;;:,:,' '"^`(f{+{>' .<{t(I!}/||t> ^(//}>;:1\\]: "[:"` ^<: . II.'.. \s - ///////////////ttt//tt((-!+}"'^. I, ,?<:' ,:;!>~',!_~{}-1]`^!}_+\\ttttttt/tttttttfff/tt\\(||]-?+;,:"l" '..'.. ?]l:" -(lI;,~?~!IIIlllI:IIlI;IIIIlllllllIIIIIllII!; . . '^^;~), "~!}\\/t//\\\\/_. '". '_i !i''' \s - tt//t///ttt///(]<>l>][l"'.`,. ^.^. ii ;; ~>>>. .i~I'^^<}), .;|tfftttttttttttf\\]}t-!,,I` .^ '. !: . .",I;. ^,I<)/-l:;llllllI;lIll;;IIIIlllIllIlIIlIllI;><. ' .;}". '.:+](ft\\}(t/t{;<\\{l^>}!^l\\/{>1/t(lI:I!+<<". ':" \s - t//tttt|?+!I!:' '` .`. ...... `^ "<^.;`^"'`,!".,^^^.,?)!. [f/+>(/tttft\\tff|+^,!' '^: >[,++:`' .I^ . _?!:^. ;~{/?//)! __::. ':. '. \s - t/\\}[{]",il'`!-<-]:`'^` .. '' .^+:'. .^'"i:`^. ';`:<_|>'.?/t/!"<)ffftf)]]!'II.,l ^' ''. '";" .' `Il, ;]>]j_;lI;ll;!!llIII>~IIIIII;: ;,~.',.<:`, 'I_|\\; .i|/]^ ?(}\\/////\\i' '' ....'^ \s - tf1<}i `^. `I` .I?"'. . . ^' .^' .'` .". >}_.I|t{_(tf({~,~(); ')t};.><,. .. . .. . . .]}^{j1IlllIlI!1IlllII?{IIIIIlI;[1!I;IIllIIlIIllI<]_;+/t\\(|\\/1,' "` ... \s - )+::((:^' ll .,` . . ..'. ' :+'`{tj{,l: ^;"..;!"^.I?' '~; .` .'. . `1+ [x?-:lIlll!]r-IllI~~{~I>lllll[i\\--+;;I~IIIII!l;x] "I"-<<_> >i.' l{}:itf/}[/\\)(\\}))|(:^^..'. `". \s - >.._f|i.:l,;^^''__. .^' `' "+,`]1i`!1_. ^l: .". .` '1I +JIt!IIlll;]\\) >1}c(_i(!IllI_l;(f. ,_";~~+^ .. .;-i '+([i+: !//1](||/\\(?:^..^^ \s - i'"}_,.` ''^... '. `. ^<`_> .. +x??_~]:[|!,.ll` . {+ ;Y[^|,>~IlIIf\\ {/;I!\\ [[-'<+l-{ _??]f\\n]lllI[!;1v` `+"]-}]~" ..'`l, ''i-` l+?\\\\\\/t{!)t[:' .^^ \s - ;,:: :,^..;:. . i+..;^ `_ ]]<-?l``-]' I>]?+. ^-|\\\\_I?]{t/?` .... \s - ^(\\]I^~?;."!" . .. . ^<^ :( >t) _[il>|+:(U<1nYQ0Xx\\> . .~xcXXYzx(n?IllI}">xCI .:1]_-" . .^. `}>!}((1-^,+?" .. \s - 1+,~I.(l' . ... ~|r:;`.+I?\\};+t) "".-?;lI>(;]xn. '_>]!+. '^'`l:11l[|((+?: . \s - [-`.':;..""' lv|. .:_(;I!u> ^,",^. .;?I]?IlI}n[^ ')(I' `tlII>x1" <}1{)l "~+ |[II;\\[:~zl .i;. .... `"i\\\\}]..!' ^.... \s - -" ` ' . ":` .|+<<;!\\U)>^ '^`' ^"I?)c-;j/ <1I~;` .!}\\(: .;"`' \s - ' 'l, .' ~[><+;!f()nn|]!:' ..^:!+1fcjx}}v!_)})>|n` ~^ ^;"'` .<+I<)/||\\i'"<"'^ `. \s - II ^}_'+_!fI?_/-jJjUr\\\\ucJJz\\|J>}?-j{]^ni" .;](),.;-<`' .^ .^' \s - +[" +]{.`i;I; ::."!??l.^Ywj}<, (n, ,~_:` .,, ` `` ' '... ^+-l,]}]}\\j/!. . ` 'I<~`'{tl..^` \s - '' .,<{[>" i/i" `-[; ,<_[>^i_l,:^_! ',+l.. ^,:,,. ;~>l;^ l> ',;I^???~,'l".. .. \s - ;{?l. !+ .. .<1i '^' "}|{:-+-;?\\[)-] ^:l1-:. '' '`, . ';.`~^ '. ..^`. \s - 'i+;]}!,. <))\\!<|ji >((_}}?t)}\\\\v|]?jI!), "lf!l. ... .^ . ". \s - .+{>` l/z\\!,>""I+~_){]vQjut_~~>>>_-<]<-)f":l_v){\\/1}}}{t/\\0?z~. ^' `-l . . .. . \s - l\\ :_>>i:^+\\)_-]!:>-+l'...`^;1!^ 'l>})l\\n\\Qt?]?]})1{][[(XC>^ ... - ^-+^.i-((?!"`:>l<[~<]nQY+?????][{\\cmO||l . ''.. - '|: '^[{~)\\_+++))1{uxnvt(t){{[[u0\\1|({1()){-?|xfc: .. \s - .<-, ]-]]]})11)){{{{}{{)|{}}{1{111{11{{}}]_!"x\\]Xf \s - ,]<\\}][[[[[[[[[[[[[[[]][[[[[[[[][[[[[[]?-+!YC{z} .` - "_[}?]][[[[[[[[[[[[[[[[[[][[[[[[[[[[[[[[[]vn\\?. ^ - ^. ;{_(_??][[[[[[[[[[[[[[[[[|[[[[[[[[[[[[[[[[v_(]^ \s - .' '. :t>/?[[[[[[[[[[[[[[[[[[[]t\\][[[[[[[[[[][]?u;()_ .. .'. . . - `. .` :)!j_]][[[]]]]][[[[[[[[[[}j(/{[[[[[][[}1{~n!)ft . .. .. . .. . - ". ..' .` . "' .^":;~ti{\\1]][]]]??]]]]][]]??[){[}[[[[?+}]!^':``^``,`;I.!<>?>:??i:;-;,<_..^,Ii: 'l,i+```' ..'!; ''. ?~.'<+ .li!:,1?}[[[[[[[[[[[[[[[[[[[[)1}]t[:, "O" . .' . ^!' . ". i+' . \s - ^. . .':`'`~/1,-<-~^'^'^^,`.."i_>^. `1t]!,^I]l^;`,I::_?]?[!:;`.`"'`l!l<1f{~>;]\\1(]I>~l!l[<,,;`lI,~},^>!>l'...'": 'x' ]l>i .:I1[~]]]]}}}}}[[}}[}}}}}[[]]]??1}}[}~;:>vx. :;..:??,.' ^` I;>.";:"^' .. ^'.^"" ' .!},' . - ~!;:!".":i"^_/|]^li(\\1;;it{' .[\\fft+<}(/{}/)|f||'.^{/[)?!:(?+-,I+fjtil"'"+fj{i:',!!;!!^:.`r. r; !l'"i1?!i>~+_?][[[?-???]][[]?-+-]??+~<_{[_l?> ''^l;l`-}<`^.i>+l ``;I":+?!~-l ,>>l.'.;. ':!!(/!":,I - /t1ffft+{jff/ttff)];)?1(/tt\\/t/tfttttfftf/1\\|t\\|/?<_]_]{<_]/f({fffjttf/[i>1//|tft|" :<~:+}, ]>if" .:-~ >) ^`^l)f(_{/\\}-+1\\()t-{j/]!:^'l<]\\)+ ."_?I_{ - ffft)|)(t[_-{tjjrjrj/{(||}(rjj\\1)I<\\((ffj/rjffttjffftrjfffrtfff/f[1jjffffftt//)}tttff/ttt[<{rj}tf1?<:~{/j)>)fttf|?)tfffftt1_;+tf1-1|~i1, >;:} '1_ ;( .. .. `:"_1{}tjtvj)vjr/|jfff/<(tf)+1/)1j)~~-[j[l|[(/\\j{:-]]([}\\t - """; - -} diff --git a/src/main/java/cc/sukazyo/cono/morny/ServerMain.java b/src/main/java/cc/sukazyo/cono/morny/ServerMain.java index c437d96..208ed1b 100644 --- a/src/main/java/cc/sukazyo/cono/morny/ServerMain.java +++ b/src/main/java/cc/sukazyo/cono/morny/ServerMain.java @@ -34,7 +34,7 @@ public class ServerMain { * {@code --version} 只输出版本信息,不运行主程序。此参数会导致其它所有参数失效(优先级最高) * *

  • - * {@code --only-hello} 只输出欢迎字符画({@link MornyHello}),不运行主程序。 + * {@code --only-hello} 只输出欢迎字符画({@link MornyAbout#MORNY_PREVIEW_IMAGE_ASCII}),不运行主程序。 * 不要同时使用 {@code --no-hello},原因见下。 *
  • *
  • @@ -222,7 +222,7 @@ public class ServerMain { //# 启动相关参数的检查和处理 //# - if (showWelcome) logger.info(MornyHello.MORNY_PREVIEW_IMAGE_ASCII); + if (showWelcome) logger.info(MornyAbout.MORNY_PREVIEW_IMAGE_ASCII); if (welcomeEchoMode) return; unknownArgs.forEach(arg -> logger.warn("Can't understand arg to some meaning :\n " + arg)); diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java index c3f78bb..e84ab3e 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java @@ -54,7 +54,8 @@ public class MornyCommands { register( new ON(), - new Hello(), new HelloOnStart(), + new Hello(), /* new {@link HelloOnStart}, */ + new MornyInfoOnHello(), new GetUsernameAndId(), new EventHack(), new Nbnhhsh(), @@ -62,7 +63,7 @@ public class MornyCommands { new Ip186Query.Whois(), new Encryptor(), new SaveData(), - new MornyInformations(), + new MornyInformation(), new Version(), new MornyRuntime(), new Jrrp(), @@ -138,7 +139,7 @@ public class MornyCommands { } private BotCommand formatTelegramCommandListLine (@Nonnull String commandName, @Nonnull String paramRule, @Nonnull String intro) { - return new BotCommand(commandName, "".equals(paramRule) ? (intro) : (paramRule+" - "+intro)); + return new BotCommand(commandName, paramRule.isEmpty() ? (intro) : (paramRule+" - "+intro)); } private boolean nonCommandExecutable (Update event, InputCommand command) { @@ -181,6 +182,11 @@ public class MornyCommands { @Nonnull @Override public String getDescription () { return "打招呼"; } @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { onCommandHelloExec(event); } } + /** + * {@link Hello} on special command /start + * Deprecated due to new {@link MornyInfoOnHello} + */ + @Deprecated @SuppressWarnings("unused") private static class HelloOnStart implements ISimpleCommand { @Nonnull @Override public String getName () { return "start"; }@Nullable @Override public String[] getAliases () { return new String[0]; }@Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { onCommandHelloExec(event); }} private static void onCommandHelloExec (@Nonnull Update event) { MornyCoeur.extra().exec(new SendSticker( @@ -227,7 +233,7 @@ public class MornyCommands { @Nullable @Override public String[] getAliases () { return null; } @Nonnull @Deprecated public String getParamRule () { return ""; } @Nonnull @Deprecated public String getDescription () { return "检查 Bot 版本信息"; } - @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { MornyInformations.echoVersion(event); } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { MornyInformation.echoVersion(event); } } private static class MornyRuntime implements ISimpleCommand { @@ -235,7 +241,7 @@ public class MornyCommands { @Nullable @Override public String[] getAliases () { return null; } @Nonnull @Deprecated public String getParamRule () { return ""; } @Nonnull @Deprecated public String getDescription () { return "获取 Bot 运行时信息(包括版本号)"; } - @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { MornyInformations.echoRuntime(event); } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { MornyInformation.echoRuntime(event); } } private static class Jrrp implements ITelegramCommand { diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInfoOnHello.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInfoOnHello.java new file mode 100644 index 0000000..245bae8 --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInfoOnHello.java @@ -0,0 +1,44 @@ +package cc.sukazyo.cono.morny.bot.command; + +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.model.request.ParseMode; +import com.pengrad.telegrambot.request.SendPhoto; + +import cc.sukazyo.cono.morny.MornyCoeur; +import cc.sukazyo.cono.morny.util.tgapi.InputCommand; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * The implementation of Telegram special command `/start`. + * + * @see MornyInformation related class where some data comes from. + * + * @since 1.0.0-RC4 + */ +public class MornyInfoOnHello implements ISimpleCommand { + + @Nonnull @Override public String getName() { return "start"; } + @Nullable @Override public String[] getAliases() { return new String[0]; } + // @Override public String getParamRule() { return ""; } + // @Override public String getDescription() { return "" } + + @Override + public void execute(@Nonnull InputCommand command, @Nonnull Update event) { + MornyCoeur.extra().exec(new SendPhoto( + event.message().chat().id(), + MornyInformation.getAboutPic() + ).caption(""" + 欢迎使用 Morny Cono来自安妮的侍从小鼠。 + Morny 具有各种各样的功能。 + + ———————————————— + %s + ———————————————— + + (你可以随时通过 /info 重新获得这些信息)""".formatted(MornyInformation.getMornyAboutLinksHTML()) + ).parseMode(ParseMode.HTML)); + } + +} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformations.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformation.java similarity index 77% rename from src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformations.java rename to src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformation.java index e9a6ad2..6a204e0 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformations.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformation.java @@ -1,14 +1,18 @@ package cc.sukazyo.cono.morny.bot.command; import cc.sukazyo.cono.morny.BuildConfig; +import cc.sukazyo.cono.morny.MornyAbout; import cc.sukazyo.cono.morny.MornyCoeur; import cc.sukazyo.cono.morny.MornySystem; +import cc.sukazyo.cono.morny.data.TelegramImages; import cc.sukazyo.cono.morny.data.TelegramStickers; import cc.sukazyo.cono.morny.util.tgapi.ExtraAction; import cc.sukazyo.cono.morny.util.tgapi.InputCommand; + import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.request.ParseMode; import com.pengrad.telegrambot.request.SendMessage; +import com.pengrad.telegrambot.request.SendPhoto; import com.pengrad.telegrambot.request.SendSticker; import javax.annotation.Nonnull; @@ -21,7 +25,7 @@ import static cc.sukazyo.cono.morny.util.CommonFormat.formatDate; import static cc.sukazyo.cono.morny.util.CommonFormat.formatDuration; import static cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml; -public class MornyInformations implements ITelegramCommand { +public class MornyInformation implements ITelegramCommand { private static final String SUB_STICKER = "stickers"; private static final String SUB_RUNTIME = "runtime"; @@ -30,14 +34,14 @@ public class MornyInformations implements ITelegramCommand { @Nonnull @Override public String getName () { return "info"; } @Nullable @Override public String[] getAliases () { return new String[0]; } - @Nonnull @Override public String getParamRule () { return "[subcommand]"; } + @Nonnull @Override public String getParamRule () { return "[(version|runtime|stickers[.IDs])]"; } @Nonnull @Override public String getDescription () { return "输出当前 Morny 的各种信息"; } @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { if (!command.hasArgs()) { - echoRuntime(event); + echoInfo(event.message().chat().id(), event.message().messageId()); return; } @@ -56,7 +60,26 @@ public class MornyInformations implements ITelegramCommand { } /** - * /info 子命令 {@value #SUB_STICKER} + * Subcommand /info without params. + * + * @since 1.0.0-RC4 + */ + public void echoInfo (long chatId, int replayToMessage) { + MornyCoeur.extra().exec(new SendPhoto( + chatId, + getAboutPic() + ).caption(""" + Morny Cono + 来自安妮的侍从小鼠。 + ———————————————— + %s""".formatted(getMornyAboutLinksHTML()) + ).parseMode(ParseMode.HTML).replyToMessageId(replayToMessage)); + } + + /** + * subcommand /info stickers + * + * @see #SUB_STICKER */ public void echoStickers (@Nonnull InputCommand command, @Nonnull Update event) { final long echoTo = event.message().chat().id(); @@ -78,22 +101,28 @@ public class MornyInformations implements ITelegramCommand { } /** - * 向 telegram 输出一个或全部 sticker + * 向 telegram 输出一个或全部 sticker. + * * @param id * sticker 在 {@link TelegramStickers} 中的字段名。 * 使用 {@link ""}(空字符串)(不是{@link null}) 表示输出全部 sticker * @param chatId 目标 chat id - * @param messageId 要回复的消息 id,特殊值跟随上游逻辑 + * @param messageId 要回复的消息 id,依据 {@link TelegramStickers#echoStickerByID(String, ExtraAction, long, int) 上游} + * 逻辑,使用 {@link -1} 表示不回复消息。 + * * @see TelegramStickers#echoStickerByID(String, ExtraAction, long, int) * @see TelegramStickers#echoAllStickers(ExtraAction, long, int) */ public static void echoStickers (@Nonnull String id, long chatId, int messageId) { - if ("".equals(id)) TelegramStickers.echoAllStickers(MornyCoeur.extra(), chatId, messageId); + if (id.isEmpty()) TelegramStickers.echoAllStickers(MornyCoeur.extra(), chatId, messageId); else TelegramStickers.echoStickerByID(id, MornyCoeur.extra(), chatId, messageId); } /** - * /info 子命令 {@value #SUB_RUNTIME} + * Subcommand /info runtime. + * + * @see #SUB_RUNTIME + * * @since 1.0.0-alpha4 */ public static void echoRuntime (@Nonnull Update event) { @@ -146,7 +175,11 @@ public class MornyInformations implements ITelegramCommand { } /** - * /info 子命令 {@value #SUB_VERSION} + * Subcommand /info version or /info v. + * + * @see #SUB_VERSION + * @see #SUB_VERSION_2 + * * @since 1.0.0-alpha4 */ public static void echoVersion (@Nonnull Update event) { @@ -175,11 +208,13 @@ public class MornyInformations implements ITelegramCommand { /** * 取得 {@link MornySystem} 的 git commit 相关版本信息的 HTML 格式化标签. + * * @return 格式类似于 {@code 28e8c82a.δ} 的以 HTML 方式格式化的版本号组件。 * 其中 {@code .δ} 对应着 {@link MornySystem#isCleanBuild}; * commit tag 字段如果支援 {@link MornySystem#currentCodePath} 则会以链接形式解析,否则则为 code 格式 * 为了对 telegram api html 格式兼容所以不支援嵌套链接与code标签。 * 如果 {@link MornySystem#isGitBuild} 为 {@link false},则方法会返回 {@link ""} + * * @since 1.0.0-beta2 */ @Nonnull @@ -226,6 +261,18 @@ public class MornyInformations implements ITelegramCommand { } } + /** + * Get the about-pic (intro picture or featured image) of Morny. + * + * @return the Telegram file binary data of the about-pic. + * @throws IllegalStateException {@link TelegramImages.AssetsFileImage#get() get() image data} may + * throws {@link IllegalStateException} while read error. + */ + @Nonnull + public static byte[] getAboutPic () { + return TelegramImages.IMG_ABOUT.get(); + } + private static void echo404 (@Nonnull Update event) { MornyCoeur.extra().exec(new SendSticker( event.message().chat().id(), @@ -233,4 +280,22 @@ public class MornyInformations implements ITelegramCommand { ).replyToMessageId(event.message().messageId())); } + /** + * The formatted about links of Morny Cono and Morny Coeur. + *

    + * With the Telegram HTML formatting, used in /info and /start. + * Provided the end user the links that can find resources about Morny. + */ + @Nonnull + public static String getMornyAboutLinksHTML () { + return """ + source code | backup + 反馈 / issue tracker + 使用说明书 / user guide & docs""".formatted( + MornyAbout.MORNY_SOURCECODE_LINK, MornyAbout.MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK, + MornyAbout.MORNY_ISSUE_TRACKER_LINK, + MornyAbout.MORNY_USER_GUIDE_LINK + ); + } + } diff --git a/src/main/java/cc/sukazyo/cono/morny/daemon/MornyReport.java b/src/main/java/cc/sukazyo/cono/morny/daemon/MornyReport.java index 0aa990e..11a646c 100644 --- a/src/main/java/cc/sukazyo/cono/morny/daemon/MornyReport.java +++ b/src/main/java/cc/sukazyo/cono/morny/daemon/MornyReport.java @@ -1,7 +1,7 @@ package cc.sukazyo.cono.morny.daemon; import cc.sukazyo.cono.morny.*; -import cc.sukazyo.cono.morny.bot.command.MornyInformations; +import cc.sukazyo.cono.morny.bot.command.MornyInformation; import cc.sukazyo.cono.morny.util.tgapi.event.EventRuntimeException; import cc.sukazyo.cono.morny.util.tgapi.formatting.TGToString; import com.google.gson.GsonBuilder; @@ -88,7 +88,7 @@ public class MornyReport { as config fields: %s """, - MornyInformations.getVersionAllFullTagHtml(), + MornyInformation.getVersionAllFullTagHtml(), MornyCoeur.getUsername(), sectionConfigFields(MornyCoeur.config()) ) diff --git a/src/main/java/cc/sukazyo/cono/morny/data/TelegramImages.java b/src/main/java/cc/sukazyo/cono/morny/data/TelegramImages.java new file mode 100644 index 0000000..f433c65 --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/data/TelegramImages.java @@ -0,0 +1,81 @@ +package cc.sukazyo.cono.morny.data; + +import cc.sukazyo.cono.morny.MornyAssets; +import cc.sukazyo.cono.morny.daemon.MornyReport; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.io.InputStream; + +import static cc.sukazyo.cono.morny.Log.exceptionLog; +import static cc.sukazyo.cono.morny.Log.logger; + +/** + * The images of morny will use. + * + * @since 1.0.0-RC4 + */ +public class TelegramImages { + + /** + * Image that stored in the {@link MornyAssets#pack}. + *

    + * It has a final {@link #assetsPath} record that is its store location, + * and has a {@link #cache} of the binary data. + * + * @since 1.0.0-RC4 + */ + public static class AssetsFileImage { + + /** the path where the image is stored in {@link MornyAssets#pack}. */ + @Nonnull private final String assetsPath; + /** the binary data cache of the image.

    {@link null} means it hasn't been cached. */ + @Nullable private byte[] cache = null; + + /** + * An {@link AssetsFileImage}. + * + * @param path the image path relative to {@link MornyAssets#pack}'s root. + */ + AssetsFileImage (@Nonnull String path) { + this.assetsPath = path; + } + + /** + * Get the binary data. + *

    + * Will read the {@link #cache} firstly. If read {@link null}, + * then it will try {@link #read load the file}, and read again. + * + * @return The binary data of the image. + * @throws IllegalStateException While the {@link #read()} failed to read data and + * the result {@link #cache} is still null + */ + @Nonnull public byte[] get() { + if (cache == null) read(); + if (cache == null) throw new IllegalStateException("Failed get assets file image."); + return cache; + } + + /** + * Load the file from {@link MornyAssets#pack}, and stored the binary data to {@link #cache}. + *

    + * If failed, it will output the exception to the log and the {@link MornyReport}, + * and remains the cache's current data. + */ + private void read() { + try (InputStream stream = MornyAssets.pack.getResource(assetsPath).read()) { + this.cache = stream.readAllBytes(); + } catch (IOException e) { + logger.error("Cannot read resource file"); + logger.error(exceptionLog(e)); + MornyReport.exception(e, "Cannot read resource file"); + } + } + + } + + public static final AssetsFileImage IMG_ABOUT = new AssetsFileImage("images/featured-image@0.5x.jpg"); + +} diff --git a/src/main/resources/assets_morny/images/featured-image@0.5x.jpg b/src/main/resources/assets_morny/images/featured-image@0.5x.jpg new file mode 100644 index 0000000..444cf8f Binary files /dev/null and b/src/main/resources/assets_morny/images/featured-image@0.5x.jpg differ diff --git a/src/main/resources/assets_morny/texts/server-hello.txt b/src/main/resources/assets_morny/texts/server-hello.txt new file mode 100644 index 0000000..96136ec --- /dev/null +++ b/src/main/resources/assets_morny/texts/server-hello.txt @@ -0,0 +1,55 @@ +ttt///t/////fucj(\tvnxtf{< .' .. .:i` . . ^!`l|-^i+,!_[:1/|{i?//\//jf\\\///\\\\//\\\//////\\/\\\\\\\\\\\\\\//\\\\/\\\\/\\//\\\///\\\\\\\\\\\\\\\\\\\\fnncvvU0O00QCx!!". .. ` +tt//////////\jzjrucnjt/?{j,,"' . .' .. .":. .;{: ' "`.,1(<."i?)\(-}\\\(((\\/\\\\\\\\\\\\\\\\///\//////\\\\\\\\\\\\\\\\\\\\\\\|\\\\\\///\\///\\\\\\\\|\\\\\\|\\\\\\\\tvXvuXcxn/[Il)({_:.. ."` ., +//////////////////\////|)/([}-_<+[]>.^^""[<'`^` .''""`'.`'`"i! ^!>l:' :<" !!.IiI`+l^^`i>_<`??)1;^{\\\\\{|({({|/\]I)\\()\(]}|\\||\|||\/\\\\\\|||\\\\\\\\//\\\\/\\\\||\\\\\\\\//\\\\\\\\\\\/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\//\\\\\\\\\\\\////\\\\\\\\\//|{{?{|)[[-; +ttt/tt//////////////////{)(\t(/tt/1~I}{-1\_^])1_+[{|(?"<1~>>+!+[}11)}[(1}]};^1\|~_1}{I:-1(I+)(|))|\\/////////\\////\\\/////\\\\\\\\\\\\\\/\//\\///\//||\////|)(//\\///){\/\(11|///({)//({[1\\\\\\\\\\|\/\\\/\//////////\\\\\\\\\//\\\\\///////\|\\\\//////\\///\ +tttt/////////////\///////\||///////t//|(|)|}|\/(\\(//(l_{{. ... ">+<^'I!: ^<(\\1}1//\\\//////////\\///\/\///\\\\\\//\\//\\\\\\\\\\\\\\///\(/\{ +t////////////////////////////////////////////////////////\/\\///////\\\\\\\\\\\\\\\/\\\\\\||\|\\\\\|\\\\/\\|\\\\\\////((|///}!:,":,^`. .;' ' '^..':. ^!;. .^^ '^^`. '' ...I[{!>:^;_i:'~\ttt/////tt//\\////////////\\\\/\\\\\\/\\\\/\\\\\)}-+[+I??i +ttt////////////////////////////////////////////////////////\\//\//\\/\\\\\\\\\\//\\\\\\||\\\/\//\\\\\\\\\/\|\\\////\1;``^;<>+!">__+I `' .. "'. .;" ;;. .:^ ``,,;'` .;]I ,-_-|\////t////t///////\/\\\\//\\\\\\//\\\///////-II1ttt///tttt/////////\/\/////\\\\////t|+<}?!-]l<{[[1-+] +t//////////////////////////////////////\/////////\////////////////\//////\//tttttttttt//////////////////////////)_)t)|}1f/{<.^,^:~: . .. '''^:-|/> '-/}-_?\/)-{?(//\(\tt////\///\\\\\\\///t1.;); .l~` '" +///////////////////////////////////////////tt/t(|tt//]+{t\{][|////\//////////ttttt///t//t/////////////\//////|//{[|f}!l>~++~<<\//]l~?])tt//\\\\\/\\///\\|?<_}["^!;I^;]:. . +////////////////////////////////tttt/|{[1)]~!!+>!<_(/|[-<"i!l,]tt//ttt/t////ttt//t///ttttttt////////t//t//ttt){+. :?^ '. l_-!+l;;;|!!>~~il!lllllllllll!!lI:`'. .' :I;]_}>,?tf:.+fft)l+1//\~`'I-(//\/t/|/(-1[)/?>>II:' '.`';-'` +/////////////////////////t//()\1_<>il^'''' ,!>;.,.'{tti `~tf(`'-(|fffftttttttttt/tttttttttttt///tttft//(t|]?-+!^ ."`. `. ;!I,. .?{il-\_!~<>>!lII;IllIIIIIllllllllllI;;:,:,' '"^`(f{+{>' .<{t(I!}/||t> ^(//}>;:1\]: "[:"` ^<: . II.'.. +///////////////ttt//tt((-!+}"'^. I, ,?<:' ,:;!>~',!_~{}-1]`^!}_+\ttttttt/tttttttfff/tt\(||]-?+;,:"l" '..'.. ?]l:" -(lI;,~?~!IIIlllI:IIlI;IIIIlllllllIIIIIllII!; . . '^^;~), "~!}\/t//\\/_. '". '_i !i''' +tt//t///ttt///(]<>l>][l"'.`,. ^.^. ii ;; ~>>>. .i~I'^^<}), .;|tfftttttttttttf\]}t-!,,I` .^ '. !: . .",I;. ^,I<)/-l:;llllllI;lIll;;IIIIlllIllIlIIlIllI;><. ' .;}". '.:+](ft\}(t/t{;<\{l^>}!^l\/{>1/t(lI:I!+<<". ':" +t//tttt|?+!I!:' '` .`. ...... `^ "<^.;`^"'`,!".,^^^.,?)!. [f/+>(/tttft\tff|+^,!' '^: >[,++:`' .I^ . _?!:^. ;~{/?//)! __::. ':. '. +t/\}[{]",il'`!-<-]:`'^` .. '' .^+:'. .^'"i:`^. ';`:<_|>'.?/t/!"<)ffftf)]]!'II.,l ^' ''. '";" .' `Il, ;]>]j_;lI;ll;!!llIII>~IIIIII;: ;,~.',.<:`, 'I_|\; .i|/]^ ?(}\/////\i' '' ....'^ +tf1<}i `^. `I` .I?"'. . . ^' .^' .'` .". >}_.I|t{_(tf({~,~(); ')t};.><,. .. . .. . . .]}^{j1IlllIlI!1IlllII?{IIIIIlI;[1!I;IIllIIlIIllI<]_;+/t\(|\/1,' "` ... +)+::((:^' ll .,` . . ..'. ' :+'`{tj{,l: ^;"..;!"^.I?' '~; .` .'. . `1+ [x?-:lIlll!]r-IllI~~{~I>lllll[i\--+;;I~IIIII!l;x] "I"-<<_> >i.' l{}:itf/}[/\)(\}))|(:^^..'. `". +>.._f|i.:l,;^^''__. .^' `' "+,`]1i`!1_. ^l: .". .` '1I +JIt!IIlll;]\) >1}c(_i(!IllI_l;(f. ,_";~~+^ .. .;-i '+([i+: !//1](||/\(?:^..^^ +i'"}_,.` ''^... '. `. ^<`_> .. +x??_~]:[|!,.ll` . {+ ;Y[^|,>~IlIIf\ {/;I!\ [[-'<+l-{ _??]f\n]lllI[!;1v` `+"]-}]~" ..'`l, ''i-` l+?\\\/t{!)t[:' .^^ +;,:: :,^..;:. . i+..;^ `_ ]]<-?l``-]' I>]?+. ^-|\\_I?]{t/?` .... +^(\]I^~?;."!" . .. . ^<^ :( >t) _[il>|+:(U<1nYQ0Xx\> . .~xcXXYzx(n?IllI}">xCI .:1]_-" . .^. `}>!}((1-^,+?" .. +1+,~I.(l' . ... ~|r:;`.+I?\};+t) "".-?;lI>(;]xn. '_>]!+. '^'`l:11l[|((+?: . +[-`.':;..""' lv|. .:_(;I!u> ^,",^. .;?I]?IlI}n[^ ')(I' `tlII>x1" <}1{)l "~+ |[II;\[:~zl .i;. .... `"i\\}]..!' ^.... +-" ` ' . ":` .|+<<;!\U)>^ '^`' ^"I?)c-;j/ <1I~;` .!}\(: .;"`' +' 'l, .' ~[><+;!f()nn|]!:' ..^:!+1fcjx}}v!_)})>|n` ~^ ^;"'` .<+I<)/||\i'"<"'^ `. + II ^}_'+_!fI?_/-jJjUr\\ucJJz\|J>}?-j{]^ni" .;](),.;-<`' .^ .^' + +[" +]{.`i;I; ::."!??l.^Ywj}<, (n, ,~_:` .,, ` `` ' '... ^+-l,]}]}\j/!. . ` 'I<~`'{tl..^` + '' .,<{[>" i/i" `-[; ,<_[>^i_l,:^_! ',+l.. ^,:,,. ;~>l;^ l> ',;I^???~,'l".. .. + ;{?l. !+ .. .<1i '^' "}|{:-+-;?\[)-] ^:l1-:. '' '`, . ';.`~^ '. ..^`. + 'i+;]}!,. <))\!<|ji >((_}}?t)}\\v|]?jI!), "lf!l. ... .^ . ". + .+{>` l/z\!,>""I+~_){]vQjut_~~>>>_-<]<-)f":l_v){\/1}}}{t/\0?z~. ^' `-l . . .. . + l\ :_>>i:^+\)_-]!:>-+l'...`^;1!^ 'l>})l\n\Qt?]?]})1{][[(XC>^ ... + ^-+^.i-((?!"`:>l<[~<]nQY+?????][{\cmO||l . ''.. + '|: '^[{~)\_+++))1{uxnvt(t){{[[u0\1|({1()){-?|xfc: .. + .<-, ]-]]]})11)){{{{}{{)|{}}{1{111{11{{}}]_!"x\]Xf + ,]<\}][[[[[[[[[[[[[[[]][[[[[[[[][[[[[[]?-+!YC{z} .` + "_[}?]][[[[[[[[[[[[[[[[[[][[[[[[[[[[[[[[[]vn\?. ^ + ^. ;{_(_??][[[[[[[[[[[[[[[[[|[[[[[[[[[[[[[[[[v_(]^ + .' '. :t>/?[[[[[[[[[[[[[[[[[[[]t\][[[[[[[[[[][]?u;()_ .. .'. . . + `. .` :)!j_]][[[]]]]][[[[[[[[[[}j(/{[[[[[][[}1{~n!)ft . .. .. . .. . + ". ..' .` . "' .^":;~ti{\1]][]]]??]]]]][]]??[){[}[[[[?+}]!^':``^``,`;I.!<>?>:??i:;-;,<_..^,Ii: 'l,i+```' ..'!; ''. ?~.'<+ .li!:,1?}[[[[[[[[[[[[[[[[[[[[)1}]t[:, "O" . .' . ^!' . ". i+' . +^. . .':`'`~/1,-<-~^'^'^^,`.."i_>^. `1t]!,^I]l^;`,I::_?]?[!:;`.`"'`l!l<1f{~>;]\1(]I>~l!l[<,,;`lI,~},^>!>l'...'": 'x' ]l>i .:I1[~]]]]}}}}}[[}}[}}}}}[[]]]??1}}[}~;:>vx. :;..:??,.' ^` I;>.";:"^' .. ^'.^"" ' .!},' . +~!;:!".":i"^_/|]^li(\1;;it{' .[\fft+<}(/{}/)|f||'.^{/[)?!:(?+-,I+fjtil"'"+fj{i:',!!;!!^:.`r. r; !l'"i1?!i>~+_?][[[?-???]][[]?-+-]??+~<_{[_l?> ''^l;l`-}<`^.i>+l ``;I":+?!~-l ,>>l.'.;. ':!!(/!":,I +/t1ffft+{jff/ttff)];)?1(/tt\/t/tfttttfftf/1\|t\|/?<_]_]{<_]/f({fffjttf/[i>1//|tft|" :<~:+}, ]>if" .:-~ >) ^`^l)f(_{/\}-+1\()t-{j/]!:^'l<]\)+ ."_?I_{ +ffft)|)(t[_-{tjjrjrj/{(||}(rjj\1)I<\((ffj/rjffttjffftrjfffrtfff/f[1jjffffftt//)}tttff/ttt[<{rj}tf1?<:~{/j)>)fttf|?)tfffftt1_;+tf1-1|~i1, >;:} '1_ ;( .. .. `:"_1{}tjtvj)vjr/|jfff/<(tf)+1/)1j)~~-[j[l|[(/\j{:-]]([}\t