Add auto publish feature

This commit is contained in:
Wieland Schöbl
2020-08-14 22:43:53 +02:00
parent d15fb92acf
commit 7bf483ab32
15 changed files with 274 additions and 130 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
servers.json servers.json
admin.json admin.json
test.json
*.hprof *.hprof
/build /build
/.gradle /.gradle

7
.idea/dictionaries/wulkanat.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="wulkanat">
<words>
<w>crosspost</w>
</words>
</dictionary>
</component>

1
.idea/gradle.xml generated
View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>

116
.idea/workspace.xml generated
View File

@@ -3,8 +3,7 @@
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="1aabf22b-2f57-46ac-9973-367d8668ffd3" name="Default Changelist" comment=""> <list default="true" id="1aabf22b-2f57-46ac-9973-367d8668ffd3" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/Admin.kt" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/Admin.kt" afterDir="false" /> <change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/Main.kt" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/Main.kt" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -85,9 +84,10 @@
<component name="FileTemplateManagerImpl"> <component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES"> <option name="RECENT_TEMPLATES">
<list> <list>
<option value="Kotlin File" />
<option value="Kotlin Class" />
<option value="Kotlin Object" /> <option value="Kotlin Object" />
<option value="Kotlin File" />
<option value="Class" />
<option value="Kotlin Class" />
</list> </list>
</option> </option>
</component> </component>
@@ -103,6 +103,8 @@
</component> </component>
<component name="PropertiesComponent"> <component name="PropertiesComponent">
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" /> <property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/src" />
<property name="project.structure.last.edited" value="Modules" /> <property name="project.structure.last.edited" value="Modules" />
<property name="project.structure.proportion" value="0.15" /> <property name="project.structure.proportion" value="0.15" />
<property name="project.structure.side.proportion" value="0.2" /> <property name="project.structure.side.proportion" value="0.2" />
@@ -112,13 +114,16 @@
<key name="MoveKotlinTopLevelDeclarationsDialog.RECENTS_KEY"> <key name="MoveKotlinTopLevelDeclarationsDialog.RECENTS_KEY">
<recent name="de.wulkanat" /> <recent name="de.wulkanat" />
</key> </key>
<key name="CopyFile.RECENT_KEYS">
<recent name="E:\Projects\Kotlin_Proj\HytaleUpdateBot\src" />
</key>
<key name="MoveFile.RECENT_KEYS"> <key name="MoveFile.RECENT_KEYS">
<recent name="E:\Projects\Kotlin_Proj\HytaleUpdateBot\src\main\kotlin\de\wulkanat" />
<recent name="E:\Projects\Kotlin_Proj\HytaleUpdateBot" /> <recent name="E:\Projects\Kotlin_Proj\HytaleUpdateBot" />
<recent name="E:\Projects\Kotlin_Proj\HytaleUpdateBot\src\main\kotlin\de\wulkanat" />
</key> </key>
</component> </component>
<component name="RunManager" selected="Gradle.HytaleUpdateBot [fatJar]"> <component name="RunManager" selected="Kotlin.MainKt">
<configuration name="HytaleUpdateBot [fatJar]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true"> <configuration name="HytaleUpdateBot [build]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings> <ExternalSystemSettings>
<option name="executionName" /> <option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
@@ -129,7 +134,7 @@
</option> </option>
<option name="taskNames"> <option name="taskNames">
<list> <list>
<option value="fatJar" /> <option value="build" />
</list> </list>
</option> </option>
<option name="vmOptions" /> <option name="vmOptions" />
@@ -137,7 +142,7 @@
<GradleScriptDebugEnabled>true</GradleScriptDebugEnabled> <GradleScriptDebugEnabled>true</GradleScriptDebugEnabled>
<method v="2" /> <method v="2" />
</configuration> </configuration>
<configuration name="HytaleUpdateBot [jar]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true"> <configuration name="HytaleUpdateBot [clean]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings> <ExternalSystemSettings>
<option name="executionName" /> <option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
@@ -148,7 +153,7 @@
</option> </option>
<option name="taskNames"> <option name="taskNames">
<list> <list>
<option value="jar" /> <option value="clean" />
</list> </list>
</option> </option>
<option name="vmOptions" /> <option name="vmOptions" />
@@ -160,21 +165,30 @@
<option name="JAR_PATH" value="$PROJECT_DIR$/build/libs/HytaleUpdateBot-1.0-SNAPSHOT-all.jar" /> <option name="JAR_PATH" value="$PROJECT_DIR$/build/libs/HytaleUpdateBot-1.0-SNAPSHOT-all.jar" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
<configuration name="HytaleUpdateBot-1.0-SNAPSHOT.jar" type="JarApplication" temporary="true">
<option name="JAR_PATH" value="$PROJECT_DIR$/build/libs/HytaleUpdateBot-1.0-SNAPSHOT.jar" />
<method v="2" />
</configuration>
<configuration name="HytaleUpdateBot-all-1.0-SNAPSHOT.jar" type="JarApplication" temporary="true"> <configuration name="HytaleUpdateBot-all-1.0-SNAPSHOT.jar" type="JarApplication" temporary="true">
<option name="JAR_PATH" value="$PROJECT_DIR$/build/libs/HytaleUpdateBot-all-1.0-SNAPSHOT.jar" /> <option name="JAR_PATH" value="$PROJECT_DIR$/build/libs/HytaleUpdateBot-all-1.0-SNAPSHOT.jar" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
<configuration name="MainKt" type="JetRunConfigurationType" temporary="true" nameIsGenerated="true">
<module name="HytaleUpdateBot.main" />
<option name="VM_PARAMETERS" />
<option name="PROGRAM_PARAMETERS" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="MAIN_CLASS_NAME" value="de.wulkanat.MainKt" />
<option name="WORKING_DIRECTORY" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<recent_temporary> <recent_temporary>
<list> <list>
<item itemvalue="Kotlin.MainKt" />
<item itemvalue="Gradle.HytaleUpdateBot [build]" />
<item itemvalue="Gradle.HytaleUpdateBot [clean]" />
<item itemvalue="JAR Application.HytaleUpdateBot-all-1.0-SNAPSHOT.jar" /> <item itemvalue="JAR Application.HytaleUpdateBot-all-1.0-SNAPSHOT.jar" />
<item itemvalue="JAR Application.HytaleUpdateBot-1.0-SNAPSHOT-all.jar" /> <item itemvalue="JAR Application.HytaleUpdateBot-1.0-SNAPSHOT-all.jar" />
<item itemvalue="Gradle.HytaleUpdateBot [fatJar]" />
<item itemvalue="JAR Application.HytaleUpdateBot-1.0-SNAPSHOT.jar" />
<item itemvalue="Gradle.HytaleUpdateBot [jar]" />
</list> </list>
</recent_temporary> </recent_temporary>
</component> </component>
@@ -189,13 +203,25 @@
<option name="presentableId" value="Default" /> <option name="presentableId" value="Default" />
<updated>1597322033373</updated> <updated>1597322033373</updated>
</task> </task>
<task id="LOCAL-00001" summary="Add auto publish feature">
<created>1597437833375</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1597437833375</updated>
</task>
<option name="localTasksCounter" value="2" />
<servers /> <servers />
</component> </component>
<component name="VcsManagerConfiguration">
<MESSAGE value="Add auto publish feature" />
<option name="LAST_COMMIT_MESSAGE" value="Add auto publish feature" />
</component>
<component name="WindowStateProjectService"> <component name="WindowStateProjectService">
<state x="552" y="179" key="#Project_Structure" timestamp="1597338262424"> <state x="552" y="179" key="#Project_Structure" timestamp="1597434105164">
<screen x="0" y="0" width="1920" height="1040" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
<state x="552" y="179" key="#Project_Structure/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597338262424" /> <state x="552" y="179" key="#Project_Structure/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597434105164" />
<state x="-1050" y="581" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1597352463714"> <state x="-1050" y="581" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1597352463714">
<screen x="-1050" y="105" width="1050" height="1640" /> <screen x="-1050" y="105" width="1050" height="1640" />
</state> </state>
@@ -204,6 +230,10 @@
<screen x="0" y="0" width="1920" height="1040" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
<state x="633" y="446" key="#com.intellij.refactoring.move.MoveHandler.SelectRefactoringDialog/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597362173063" /> <state x="633" y="446" key="#com.intellij.refactoring.move.MoveHandler.SelectRefactoringDialog/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597362173063" />
<state x="690" y="268" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog" timestamp="1597428556346">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state x="690" y="268" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597428556346" />
<state x="739" y="173" width="484" height="693" key="#org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.MoveKotlinTopLevelDeclarationsDialog" timestamp="1597362199927"> <state x="739" y="173" width="484" height="693" key="#org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.MoveKotlinTopLevelDeclarationsDialog" timestamp="1597362199927">
<screen x="0" y="0" width="1920" height="1040" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
@@ -212,51 +242,59 @@
<screen x="0" y="0" width="1920" height="1040" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
<state x="128" y="270" width="490" height="591" key="#xdebugger.evaluate/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597332665464" /> <state x="128" y="270" width="490" height="591" key="#xdebugger.evaluate/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597332665464" />
<state width="1876" height="161" key="GridCell.Tab.0.bottom" timestamp="1597364285629"> <state x="569" y="115" key="CommitChangelistDialog2" timestamp="1597437831316">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state x="569" y="115" key="CommitChangelistDialog2/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597437831316" />
<state width="1876" height="161" key="GridCell.Tab.0.bottom" timestamp="1597437840934">
<screen x="0" y="0" width="1920" height="1040" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
<state width="1006" height="588" key="GridCell.Tab.0.bottom/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329412" /> <state width="1006" height="588" key="GridCell.Tab.0.bottom/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329412" />
<state width="1876" height="161" key="GridCell.Tab.0.bottom/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597364285629" /> <state width="1876" height="161" key="GridCell.Tab.0.bottom/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597437840934" />
<state width="1876" height="161" key="GridCell.Tab.0.center" timestamp="1597364285629"> <state width="1876" height="161" key="GridCell.Tab.0.center" timestamp="1597437840934">
<screen x="0" y="0" width="1920" height="1040" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
<state width="1006" height="588" key="GridCell.Tab.0.center/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329411" /> <state width="1006" height="588" key="GridCell.Tab.0.center/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329411" />
<state width="1876" height="161" key="GridCell.Tab.0.center/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597364285629" /> <state width="1876" height="161" key="GridCell.Tab.0.center/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597437840934" />
<state width="1876" height="161" key="GridCell.Tab.0.left" timestamp="1597364285629"> <state width="1876" height="161" key="GridCell.Tab.0.left" timestamp="1597437840934">
<screen x="0" y="0" width="1920" height="1040" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
<state width="1006" height="588" key="GridCell.Tab.0.left/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329411" /> <state width="1006" height="588" key="GridCell.Tab.0.left/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329411" />
<state width="1876" height="161" key="GridCell.Tab.0.left/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597364285629" /> <state width="1876" height="161" key="GridCell.Tab.0.left/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597437840934" />
<state width="1876" height="161" key="GridCell.Tab.0.right" timestamp="1597364285629"> <state width="1876" height="161" key="GridCell.Tab.0.right" timestamp="1597437840934">
<screen x="0" y="0" width="1920" height="1040" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
<state width="1006" height="588" key="GridCell.Tab.0.right/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329411" /> <state width="1006" height="588" key="GridCell.Tab.0.right/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329411" />
<state width="1876" height="161" key="GridCell.Tab.0.right/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597364285629" /> <state width="1876" height="161" key="GridCell.Tab.0.right/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597437840934" />
<state width="1006" height="588" key="GridCell.Tab.1.bottom" timestamp="1597351329412"> <state width="1006" height="588" key="GridCell.Tab.1.bottom" timestamp="1597366506508">
<screen x="-1050" y="105" width="1050" height="1640" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
<state width="1006" height="588" key="GridCell.Tab.1.bottom/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329412" /> <state width="1006" height="588" key="GridCell.Tab.1.bottom/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329412" />
<state width="1876" height="348" key="GridCell.Tab.1.bottom/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597339868293" /> <state width="1006" height="588" key="GridCell.Tab.1.bottom/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597366506508" />
<state width="1006" height="588" key="GridCell.Tab.1.center" timestamp="1597351329412"> <state width="1006" height="588" key="GridCell.Tab.1.center" timestamp="1597366506506">
<screen x="-1050" y="105" width="1050" height="1640" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
<state width="1006" height="588" key="GridCell.Tab.1.center/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329412" /> <state width="1006" height="588" key="GridCell.Tab.1.center/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329412" />
<state width="1876" height="348" key="GridCell.Tab.1.center/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597339868293" /> <state width="1006" height="588" key="GridCell.Tab.1.center/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597366506506" />
<state width="1006" height="588" key="GridCell.Tab.1.left" timestamp="1597351329412"> <state width="1006" height="588" key="GridCell.Tab.1.left" timestamp="1597366506505">
<screen x="-1050" y="105" width="1050" height="1640" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
<state width="1006" height="588" key="GridCell.Tab.1.left/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329412" /> <state width="1006" height="588" key="GridCell.Tab.1.left/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329412" />
<state width="1876" height="348" key="GridCell.Tab.1.left/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597339868293" /> <state width="1006" height="588" key="GridCell.Tab.1.left/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597366506505" />
<state width="1006" height="588" key="GridCell.Tab.1.right" timestamp="1597351329412"> <state width="1006" height="588" key="GridCell.Tab.1.right" timestamp="1597366506507">
<screen x="-1050" y="105" width="1050" height="1640" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
<state width="1006" height="588" key="GridCell.Tab.1.right/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329412" /> <state width="1006" height="588" key="GridCell.Tab.1.right/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597351329412" />
<state width="1876" height="348" key="GridCell.Tab.1.right/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597339868293" /> <state width="1006" height="588" key="GridCell.Tab.1.right/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597366506507" />
<state x="94" y="257" key="SettingsEditor" timestamp="1597361509050"> <state x="94" y="257" key="SettingsEditor" timestamp="1597361509050">
<screen x="0" y="0" width="1920" height="1040" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>
<state x="-1040" y="568" key="SettingsEditor/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597353858648" /> <state x="-1040" y="568" key="SettingsEditor/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@-1050.105.1050.1640" timestamp="1597353858648" />
<state x="94" y="257" key="SettingsEditor/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597361509050" /> <state x="94" y="257" key="SettingsEditor/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597361509050" />
<state x="552" y="254" key="Vcs.Push.Dialog.v2" timestamp="1597437834887">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state x="552" y="254" key="Vcs.Push.Dialog.v2/0.0.1920.1040/1920.-213.2560.1400/-1050.105.1050.1640@0.0.1920.1040" timestamp="1597437834887" />
<state x="616" y="240" key="run.anything.popup" timestamp="1597325088886"> <state x="616" y="240" key="run.anything.popup" timestamp="1597325088886">
<screen x="0" y="0" width="1920" height="1040" /> <screen x="0" y="0" width="1920" height="1040" />
</state> </state>

View File

@@ -3,17 +3,39 @@ A bot that automatically polls the newest blogpost from [Hytale News Tab](https:
## Setup ## Setup
Okay, this isn't really meant for you to setup, if you want it though it first is easier to just dm me on Twitter [@tale_talk](https://twitter.com/tale_talk) so I can add you to the server list. Okay, this isn't really meant for you to setup, if you want it though it first is easier to just dm me on Twitter [@tale_talk](https://twitter.com/tale_talk) so I can add you to the server list.
If you *really* want to set it up yourself, fine. If you *really* want to set it up yourself, fine.
1. first go to the release tab, download the jar, and put it in a folder * first go to the release tab, download the jar, and put it in a folder
2. Add two files in the root of the repo, an `admin.json` and a `servers.json`. * Add two files in the root of the repo, an `admin.json` and a `servers.json`.
Add your Discord ID (not name), Bot token, and update frequency to the `admin.json`: Add your Discord ID (not name), Bot token, and update frequency to the `admin.json`:
```json ```json
{"adminId": 12345678910,"token": "AOGH@(AKnjsfjiJijaig3ijgG92jaij","updateMs":30000} {
"adminId": 12345678910,
"token": "AOGH@(AKnjsfjiJijaig3ijgG92jaij",
"updateMs":30000
}
``` ```
3. add an empty array to your `servers.json` * add your servers to `servers.json`
```json ```json
[] [
{
"id": 15050067772322222,
"mentionedRole": "everyone",
"autoPublish":true
},
{
"id": 74050067772325222,
"mentionedRole": null,
"autoPublish":false
},
{
"id": 74050067772325222,
"mentionedRole": "74036067771625222",
"autoPublish":false
}
]
``` ```
Not sure, but it might be that multiline JSON doesn't work. * add a `test.json` with the same schema as the `server.json`. When
you enable test mode, the servers from there will be used instead allowing
you to test if it works.
## Compiling yourself ## Compiling yourself
I developed it under Windows, and had some trouble compiling it on Linux. You mileage may vary. I developed it under Windows, and had some trouble compiling it on Linux. You mileage may vary.
@@ -22,14 +44,22 @@ I developed it under Windows, and had some trouble compiling it on Linux. You mi
Start the server with `java -jar [server-file-name]` If you put in everything correctly, the bot should message you on Discord. Start the server with `java -jar [server-file-name]` If you put in everything correctly, the bot should message you on Discord.
### Adding Servers ### Adding Servers
Please edit the JSON file.
You can force an update by calling
``` ```
%!addChannel [channelID] [roleID/everyone] %!refreshList
``` ```
Second argument is optional. ### Testing
### Cause a fake update (test if it works) Switching between test and production files
``` ```
%!testMode
%!fakeUpdate %!fakeUpdate
``` ```
```
%!productionMode
```
**WARNING**: Initiating a fake update is not being cancelled by switching
to production.
### Stop the server from within Discord ### Stop the server from within Discord
``` ```
%!stop %!stop
@@ -45,3 +75,8 @@ It will also print errors directly in a Discord private message.
## TODO ## TODO
Mainly reaction roles for convenience, self setup on invite to server, Twitter integration. Mainly reaction roles for convenience, self setup on invite to server, Twitter integration.
## Other
Thanks to [Forcellrus](https://github.com/Forcellrus/Discord-Auto-Publisher) for discovering a way to auto publish messages
in news channels

View File

@@ -0,0 +1,27 @@
import net.dv8tion.jda.internal.requests.Method;
import net.dv8tion.jda.internal.requests.Route;
import java.lang.reflect.Constructor;
public class Inaccessibles {
/**
* This is private by default
*
* @param method look
* @param route somewhere
* @return else
*/
public static Route getRoute(Method method, String route) {
try {
Constructor<?> constructor = Route.class.getDeclaredConstructor(Method.class, String.class);
constructor.setAccessible(true);
return (Route) constructor.newInstance(method, route);
} catch (Exception e) {
return null;
}
}
public static String toUnsignedString(long num) {
return Long.toUnsignedString(num);
}
}

View File

@@ -4,17 +4,33 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration import kotlinx.serialization.json.JsonConfiguration
import net.dv8tion.jda.api.EmbedBuilder import net.dv8tion.jda.api.EmbedBuilder
import net.dv8tion.jda.api.JDA import net.dv8tion.jda.api.JDA
import net.dv8tion.jda.api.entities.Activity
import net.dv8tion.jda.api.entities.MessageEmbed import net.dv8tion.jda.api.entities.MessageEmbed
import net.dv8tion.jda.api.entities.User import net.dv8tion.jda.api.entities.User
import java.awt.Color import java.awt.Color
import java.sql.Time
import java.util.concurrent.TimeUnit
object Admin { object Admin {
val userId: Long val userId: Long
val token: String val token: String
val updateMs: Long val updateMs: Long
var testModeEnabled: Boolean = false
set(value) {
if (field == value)
return
field = value
if (value) {
jda?.presence?.setPresence(Activity.of(Activity.ActivityType.DEFAULT, "Testing mode, hold on..."), true)
} else {
jda?.presence?.setPresence(Activity.watching("for new Blogposts"), false)
}
Channels.channels = Channels.refreshFromDisk()
Admin.info()
}
init { init {
val admin = Json(JsonConfiguration.Stable).parse(AdminFile.serializer(), ADMIN_FILE.readText()) val admin = Json(JsonConfiguration.Stable).parse(AdminFile.serializer(), ADMIN_FILE.readText())
userId = admin.adminId userId = admin.adminId
@@ -55,14 +71,14 @@ object Admin {
) )
} }
fun error(msg: String, error: Exception) { fun error(msg: String, error: String) {
sendDevMessage( sendDevMessage(
EmbedBuilder() EmbedBuilder()
.setTitle(msg) .setTitle(msg)
.setDescription(error.message) .setDescription(error)
.setColor(Color.RED) .setColor(Color.RED)
.build() .build()
, "$msg\n\n${error.message}" , "$msg\n\n${error}"
) )
} }

View File

@@ -1,21 +0,0 @@
package de.wulkanat
import net.dv8tion.jda.api.events.message.MessageReceivedEvent
import net.dv8tion.jda.api.hooks.ListenerAdapter
class Bot : ListenerAdapter() {
override fun onMessageReceived(event: MessageReceivedEvent) {
val message = event.message
if (message.contentRaw == "!ping") {
val channel = message.channel
val time = System.currentTimeMillis()
channel.sendMessage("Pong!")
.queue {
it.editMessageFormat("Pong: %d ms", System.currentTimeMillis() - time)
.queue()
}
}
}
}

View File

@@ -1,5 +1,6 @@
package de.wulkanat package de.wulkanat
import de.wulkanat.extensions.crosspost
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.list import kotlinx.serialization.list
@@ -15,8 +16,7 @@ object Channels {
/** /**
* List of (ServerID, ChannelID) * List of (ServerID, ChannelID)
*/ */
val channels: MutableList<DiscordChannel> = var channels: MutableList<DiscordChannel> = refreshFromDisk()
json.parse(DiscordChannel.serializer().list, SERVERS_FILE.readText()).toMutableList()
fun sentToAll(messageEmbed: MessageEmbed) { fun sentToAll(messageEmbed: MessageEmbed) {
if (jda == null) if (jda == null)
@@ -33,7 +33,11 @@ object Channels {
} }
channel.sendMessage(message).queue() channel.sendMessage(message).queue()
} }
channel.sendMessage(messageEmbed).queue() channel.sendMessage(messageEmbed).queue {
if (channel_pair.autoPublish) {
it.crosspost().queue()
}
}
} }
} }
@@ -52,6 +56,16 @@ object Channels {
} }
} }
fun refreshFromDisk(): MutableList<DiscordChannel> {
return json.parse(
DiscordChannel.serializer().list, (if (Admin.testModeEnabled) {
TEST_FILE
} else {
SERVERS_FILE
}).readText()
).toMutableList()
}
fun getServerNames(): List<String> { fun getServerNames(): List<String> {
if (jda == null) if (jda == null)
return listOf() return listOf()
@@ -63,12 +77,10 @@ object Channels {
return@map "**${it.id}** *(inactive)*" return@map "**${it.id}** *(inactive)*"
} }
val role = if (it.mentionedRole == null) { val role = when (it.mentionedRole) {
"" null -> ""
} else if (it.mentionedRole == "everyone") { "everyone" -> " @everyone"
" @everyone" else -> " @${channel.guild.getRoleById(it.mentionedRole)?.name}"
} else {
" @${channel.guild.getRoleById(it.mentionedRole)?.name}"
} }
"**${channel.guild.name}**\n#${channel.name}${role}" "**${channel.guild.name}**\n#${channel.name}${role}"
} }
@@ -88,6 +100,7 @@ object Channels {
json.stringify( json.stringify(
DiscordChannel.serializer().list, DiscordChannel.serializer().list,
channels channels
)) )
)
} }
} }

View File

@@ -4,59 +4,47 @@ import de.wulkanat.model.BlogPostPreview
import net.dv8tion.jda.api.events.message.MessageReceivedEvent import net.dv8tion.jda.api.events.message.MessageReceivedEvent
import net.dv8tion.jda.api.hooks.ListenerAdapter import net.dv8tion.jda.api.hooks.ListenerAdapter
import de.wulkanat.web.SiteWatcher import de.wulkanat.web.SiteWatcher
import net.dv8tion.jda.api.events.ExceptionEvent
import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent
import kotlin.system.exitProcess import kotlin.system.exitProcess
class Cli : ListenerAdapter() { class Cli : ListenerAdapter() {
override fun onMessageReceived(event: MessageReceivedEvent) { override fun onPrivateMessageReceived(event: PrivateMessageReceivedEvent) {
val msg = event.message.contentRaw val msg = event.message.contentRaw
if (event.author.idLong != Admin.userId || if (event.author.idLong != Admin.userId ||
!msg.startsWith("%!") !msg.startsWith("!")
) { ) {
return return
} }
val command = msg.removePrefix("%!").split(" ") val command = msg.removePrefix("!").split(Regex("\\s+"))
try { when (command[0]) {
when (command[0]) { "stop" -> exitProcess(1)
"stop" -> exitProcess(1) "fakeUpdate" -> {
"fakeUpdate" -> { SiteWatcher.newestBlog = BlogPostPreview(
SiteWatcher.newestBlog = BlogPostPreview( title = "FakePost",
title = "FakePost", imgUrl = "",
imgUrl = "", fullPostUrl = "",
fullPostUrl = "", author = "wulkanat",
author = "wulkanat", date = "now",
date = "now", description = "Lorem Ipsum"
description = "Lorem Ipsum" )
)
Admin.println("Posting on next update cycle.") Admin.println("Posting on next update cycle.")
} }
"addChannel" -> { "info" -> {
val channel = command[1].toLong() Admin.info()
var role: String? = null }
if (command.size == 3) { "refreshList" -> {
role = command[2] Channels.channels = Channels.refreshFromDisk()
} Admin.info()
val serverChannel = Channels.testServerId(channel) }
val roleName = serverChannel?.guild?.getRoleById(role ?: "") "testMode" -> {
Admin.testModeEnabled = true
if (serverChannel != null) { }
if (roleName != null || role == null || role == "everyone") { "productionMode" -> {
Channels.addChannel(channel, role) Admin.testModeEnabled = false
Admin.println("Added server '${serverChannel.name}' for role '${roleName ?: role}'")
} else {
Admin.warning("Unknown Role ID")
}
} else {
Admin.warning("Unknown Channel ID")
}
}
"info" -> {
Admin.info()
}
} }
} catch (e: ArrayIndexOutOfBoundsException) {
// noop
} }
} }
} }

View File

@@ -6,7 +6,8 @@ import java.io.File
@Serializable @Serializable
data class DiscordChannel( data class DiscordChannel(
val id: Long, val id: Long,
val mentionedRole: String? = null val mentionedRole: String? = null,
val autoPublish: Boolean = false
) )
@Serializable @Serializable
@@ -17,4 +18,5 @@ data class AdminFile(
) )
val SERVERS_FILE = File("servers.json") val SERVERS_FILE = File("servers.json")
val TEST_FILE = File("test.json")
val ADMIN_FILE = File("admin.json") val ADMIN_FILE = File("admin.json")

View File

@@ -0,0 +1,10 @@
package de.wulkanat
import net.dv8tion.jda.api.events.ExceptionEvent
import net.dv8tion.jda.api.hooks.ListenerAdapter
class ErrorHandler : ListenerAdapter() {
override fun onException(event: ExceptionEvent) {
Admin.error(event.cause.message ?: event.cause.localizedMessage, event.cause.stackTrace.toString())
}
}

View File

@@ -7,15 +7,14 @@ import de.wulkanat.web.SiteWatcher
import kotlin.concurrent.timer import kotlin.concurrent.timer
fun main() { fun main() {
// TODO: move toke into file
val builder = JDABuilder.createLight( val builder = JDABuilder.createLight(
Admin.token, Admin.token,
GatewayIntent.GUILD_MESSAGES, GatewayIntent.DIRECT_MESSAGES) GatewayIntent.GUILD_MESSAGES, GatewayIntent.DIRECT_MESSAGES)
.addEventListeners(Bot())
.setActivity(Activity.watching("for new Blogposts")) .setActivity(Activity.watching("for new Blogposts"))
.build() .build()
builder.addEventListener(Cli()) builder.addEventListener(Cli())
builder.addEventListener(ErrorHandler())
builder.awaitReady() builder.awaitReady()
Channels.jda = builder Channels.jda = builder

View File

@@ -0,0 +1,28 @@
package de.wulkanat.extensions
import Inaccessibles
import net.dv8tion.jda.api.entities.Message
import net.dv8tion.jda.api.entities.MessageChannel
import net.dv8tion.jda.api.requests.restaction.MessageAction
import net.dv8tion.jda.internal.requests.Method
import net.dv8tion.jda.internal.requests.Route
import net.dv8tion.jda.internal.requests.restaction.MessageActionImpl
import net.dv8tion.jda.internal.utils.Checks
fun MessageChannel.crosspostById(messageId: String): MessageAction {
Checks.isSnowflake(messageId, "Message ID")
val route = CROSSPOST_MESSAGE.compile(id, messageId)
return MessageActionImpl(jda, route, this).append("This is not of your interest.")
}
fun Message.crosspost(): MessageAction {
val messageId = Inaccessibles.toUnsignedString(idLong)
return channel.crosspostById(messageId)
}
val CROSSPOST_MESSAGE: Route = Inaccessibles.getRoute(
Method.POST,
"channels/{channel_id}/messages/{message_id}/crosspost"
)

View File

@@ -27,7 +27,7 @@ object SiteWatcher {
newestBlog = newBlog newestBlog = newBlog
} }
} catch (e: IOException) { } catch (e: IOException) {
Admin.error("Connection to Hytale Server failed", e) Admin.error("Connection to Hytale Server failed", e.message ?: e.localizedMessage)
return false return false
} }