mirror of
https://github.com/HMCore/Orbot.git
synced 2025-12-10 21:06:18 +00:00
Add Twitter integration
Add Job Listening Integration Various Refactorings
This commit is contained in:
124
.idea/uiDesigner.xml
generated
Normal file
124
.idea/uiDesigner.xml
generated
Normal file
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
50
.idea/workspace.xml
generated
50
.idea/workspace.xml
generated
@@ -4,12 +4,23 @@
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="1aabf22b-2f57-46ac-9973-367d8668ffd3" name="Default Changelist" comment="Update stuff">
|
||||
<list default="true" id="1aabf22b-2f57-46ac-9973-367d8668ffd3" name="Default Changelist" comment="Add shards count configuration">
|
||||
<change afterPath="$PROJECT_DIR$/.idea/uiDesigner.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/web/Parser.kt" 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/AdminCli.kt" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/AdminCli.kt" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/DataIO.kt" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/DataIO.kt" 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" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/extensions/Jsoup.kt" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/extensions/Jsoup.kt" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/model/BlogPostPreview.kt" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/model/BlogPostPreview.kt" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/model/JobListingPreview.kt" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/model/JobListingPreview.kt" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/web/BlogPostParser.kt" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/web/JobListingParser.kt" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/web/SiteWatcher.kt" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/web/SiteWatcher.kt" afterDir="false" />
|
||||
</list>
|
||||
<list id="44283a45-f406-407f-bce2-a31bb9bfc0cc" name="Changes by Valentin" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/Channels.kt" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/kotlin/de/wulkanat/Channels.kt" afterDir="false" />
|
||||
</list>
|
||||
<list id="44283a45-f406-407f-bce2-a31bb9bfc0cc" name="Changes by Valentin" comment="" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
@@ -43,10 +54,10 @@
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
<list>
|
||||
<option value="Class" />
|
||||
<option value="Kotlin Class" />
|
||||
<option value="Kotlin Object" />
|
||||
<option value="Kotlin File" />
|
||||
<option value="Class" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
@@ -58,6 +69,14 @@
|
||||
</option>
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="GitSEFilterConfiguration">
|
||||
<file-type-list>
|
||||
<filtered-out-file-type name="LOCAL_BRANCH" />
|
||||
<filtered-out-file-type name="REMOTE_BRANCH" />
|
||||
<filtered-out-file-type name="TAG" />
|
||||
<filtered-out-file-type name="COMMIT_BY_MESSAGE" />
|
||||
</file-type-list>
|
||||
</component>
|
||||
<component name="HighlightingSettingsPerFile">
|
||||
<setting file="file://$PROJECT_DIR$/build.gradle" root0="SKIP_INSPECTION" />
|
||||
</component>
|
||||
@@ -78,14 +97,18 @@
|
||||
<property name="aspect.path.notification.shown" value="true" />
|
||||
<property name="codeWithMe.voiceChat.enabledByDefault" value="false" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||
<property name="node.js.detected.package.eslint" value="true" />
|
||||
<property name="node.js.detected.package.tslint" value="true" />
|
||||
<property name="node.js.selected.package.eslint" value="(autodetect)" />
|
||||
<property name="node.js.selected.package.tslint" value="(autodetect)" />
|
||||
<property name="project.structure.last.edited" value="Project" />
|
||||
<property name="project.structure.proportion" value="0.15" />
|
||||
<property name="project.structure.side.proportion" value="0.2" />
|
||||
<property name="settings.editor.selected.configurable" value="preferences.pluginManager" />
|
||||
</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="MoveKotlinTopLevelDeclarationsDialog.RECENTS_KEY">
|
||||
<recent name="de.wulkanat" />
|
||||
<key name="CreateClassDialog.RecentsKey">
|
||||
<recent name="org.hmcore" />
|
||||
</key>
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
<recent name="E:\Projects\Kotlin_Proj\HytaleUpdateBot\build\libs" />
|
||||
@@ -95,6 +118,9 @@
|
||||
<recent name="E:\Projects\Kotlin_Proj\HytaleUpdateBot" />
|
||||
<recent name="E:\Projects\Kotlin_Proj\HytaleUpdateBot\src\main\kotlin\de\wulkanat" />
|
||||
</key>
|
||||
<key name="MoveKotlinTopLevelDeclarationsDialog.RECENTS_KEY">
|
||||
<recent name="de.wulkanat" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunManager" selected="Kotlin.Main">
|
||||
<configuration default="true" type="ArquillianJUnit" factoryName="" nameIsGenerated="true">
|
||||
@@ -203,7 +229,7 @@
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1597322033373</updated>
|
||||
<workItem from="1622225780094" duration="598000" />
|
||||
<workItem from="1622225780094" duration="6687000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="Add auto publish feature">
|
||||
<created>1597437833375</created>
|
||||
@@ -254,7 +280,14 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1622224992757</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="8" />
|
||||
<task id="LOCAL-00008" summary="Add shards count configuration">
|
||||
<created>1622226400158</created>
|
||||
<option name="number" value="00008" />
|
||||
<option name="presentableId" value="LOCAL-00008" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1622226400158</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="9" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
@@ -280,7 +313,8 @@
|
||||
<MESSAGE value="prepare twitter integration" />
|
||||
<MESSAGE value="Update Json Serialization" />
|
||||
<MESSAGE value="Update stuff" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Update stuff" />
|
||||
<MESSAGE value="Add shards count configuration" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Add shards count configuration" />
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<watches-manager>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package de.wulkanat
|
||||
|
||||
import de.wulkanat.model.BlogPostPreview
|
||||
import de.wulkanat.web.fakeUpdateBlogPost
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter
|
||||
import de.wulkanat.web.SiteWatcher
|
||||
import net.dv8tion.jda.api.EmbedBuilder
|
||||
import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent
|
||||
import org.hmcore.TwitterJob
|
||||
@@ -24,14 +23,9 @@ class AdminCli : ListenerAdapter() {
|
||||
when (command[0].value) {
|
||||
"stop" -> exitProcess(1)
|
||||
"fakeUpdate" -> {
|
||||
SiteWatcher.newestBlog = BlogPostPreview(
|
||||
title = "FakePost",
|
||||
imgUrl = "",
|
||||
fullPostUrl = "",
|
||||
author = "wulkanat",
|
||||
date = "now",
|
||||
description = "Lorem Ipsum"
|
||||
)
|
||||
// TODO: implement fake update for blog posts
|
||||
// BLOG_POST_WATCHER.current = setOf()
|
||||
fakeUpdateBlogPost()
|
||||
|
||||
TwitterJob.lastTweetID = "poggers"
|
||||
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
package de.wulkanat
|
||||
|
||||
import de.wulkanat.extensions.ensureExists
|
||||
import de.wulkanat.model.BlogPostPreview
|
||||
import de.wulkanat.model.JobListingPreview
|
||||
import kotlinx.serialization.Required
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.io.File
|
||||
@@ -28,23 +32,32 @@ data class CustomMessage(
|
||||
|
||||
@Serializable
|
||||
data class AdminFile(
|
||||
val adminId: Long = 12345,
|
||||
val token: String = "12345",
|
||||
val updateMs: Long = 30000,
|
||||
val shards: Int = 6,
|
||||
val watchingMessage: String = "for new Blogposts",
|
||||
val offlineMessage: String = "CONNECTION FAILED",
|
||||
var twitterApi: TwitterApi? = TwitterApi()
|
||||
@Required val adminId: Long = 12345,
|
||||
@Required val token: String = "12345",
|
||||
@Required val updateMs: Long = 30000,
|
||||
@Required val shards: Int = 6,
|
||||
@Required val watchingMessage: String = "for new Blogposts",
|
||||
@Required val offlineMessage: String = "CONNECTION FAILED",
|
||||
@Required var twitterApi: TwitterApi? = TwitterApi()
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TwitterApi(
|
||||
val accessToken: String = "accessTokenHere",
|
||||
val accessTokenSecret: String = "accessTokenSecretHere",
|
||||
val apiKey: String = "apiKeyHere",
|
||||
val apiKeySecret: String = "Api Key secret here"
|
||||
@Required val accessToken: String = "accessTokenHere",
|
||||
@Required val accessTokenSecret: String = "accessTokenSecretHere",
|
||||
@Required val apiKey: String = "apiKeyHere",
|
||||
@Required val apiKeySecret: String = "Api Key secret here"
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Webhooks(
|
||||
@Required val blogPostsWebhookUrl: String = "https://...",
|
||||
@Required val jobListingsWebhookUrl: String = "https://...",
|
||||
)
|
||||
|
||||
val WEBHOOKS_FILE = File("webhooks.json").ensureExists(Json.encodeToString(Webhooks()))
|
||||
val WEBHOOKS = Json.decodeFromString<Webhooks>(WEBHOOKS_FILE.readText())
|
||||
|
||||
val SERVERS_FILE = File("servers.json").ensureExists(Json.encodeToString(listOf<DiscordChannel>()))
|
||||
val SERVICE_CHANNELS_FILE =
|
||||
File("service_channels.json").ensureExists(Json.encodeToString(listOf<ServiceChannel>()))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package de.wulkanat
|
||||
|
||||
import de.wulkanat.web.SiteWatcher
|
||||
import de.wulkanat.web.getNewBlogPosts
|
||||
import net.dv8tion.jda.api.JDA
|
||||
import net.dv8tion.jda.api.JDABuilder
|
||||
import net.dv8tion.jda.api.MessageBuilder
|
||||
@@ -59,8 +59,8 @@ object Main {
|
||||
})
|
||||
|
||||
timer("Updater", daemon = true, initialDelay = 0L, period = Admin.updateMs) {
|
||||
if (SiteWatcher.hasNewBlogPost()) {
|
||||
Channels.sentToAll(MessageBuilder().setEmbed(SiteWatcher.newestBlog!!.toMessageEmbed()).build())
|
||||
getNewBlogPosts()?.forEach {
|
||||
Channels.sentToAll(MessageBuilder().setEmbed(it.toMessageEmbed()).build())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,4 +7,5 @@ operator fun Element.get(className: String): Elements =
|
||||
this.getElementsByClass(className)
|
||||
|
||||
val Elements.text get() = text().trim()
|
||||
val Element.absUrl get(): String = child(0).absUrl("href")
|
||||
val Element.absUrl get(): String = child(0).absUrl("href")
|
||||
val Element.imgSrc get(): String = child(0).attr("src")
|
||||
@@ -3,7 +3,9 @@ package de.wulkanat.model
|
||||
import net.dv8tion.jda.api.EmbedBuilder
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed
|
||||
import de.wulkanat.extensions.hex2Rgb
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class BlogPostPreview(
|
||||
val title: String,
|
||||
val description: String,
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package de.wulkanat.model
|
||||
|
||||
import de.wulkanat.extensions.hex2Rgb
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.dv8tion.jda.api.EmbedBuilder
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed
|
||||
|
||||
class JobListingPreview(
|
||||
@Serializable
|
||||
data class JobListingPreview(
|
||||
val title: String,
|
||||
val department: String,
|
||||
val location: String,
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package de.wulkanat.web
|
||||
|
||||
import de.wulkanat.model.BlogPostPreview
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
object BlogPostParser {
|
||||
fun getFistBlog(doc: Document): BlogPostPreview {
|
||||
val posts = doc.getElementsByClass("postWrapper")
|
||||
return parseBlog(posts.first())
|
||||
}
|
||||
|
||||
private fun parseBlog(elm: Element): BlogPostPreview {
|
||||
|
||||
return BlogPostPreview(
|
||||
title = elm.getElementsByClass("post__details__heading").first().text(),
|
||||
imgUrl = elm.getElementsByClass("post__image__frame").first().child(0).attr("src"),
|
||||
fullPostUrl = elm.child(0).absUrl("href"),
|
||||
date = elm.getElementsByClass("post__details__meta__date").first().text(),
|
||||
author = elm.getElementsByClass("post__details__meta__author").first().text(),
|
||||
description = elm.getElementsByClass("post__details__body").first().text()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package de.wulkanat.web
|
||||
|
||||
import de.wulkanat.extensions.get
|
||||
import de.wulkanat.extensions.text
|
||||
import de.wulkanat.extensions.absUrl
|
||||
import de.wulkanat.model.JobListingPreview
|
||||
import org.jsoup.nodes.Document
|
||||
|
||||
fun parseJobListings(doc: Document) =
|
||||
doc["current-jobs__departments"].flatMap { jobDepartment ->
|
||||
val jobDepartmentName = jobDepartment["current-jobs__department-name"].text
|
||||
|
||||
jobDepartment["current-jobs__job"].map { job ->
|
||||
JobListingPreview(
|
||||
title = job["current-jobs__job-title"].text,
|
||||
department = jobDepartmentName,
|
||||
location = job["current-jobs__job-location"].text,
|
||||
fullListingUrl = job.absUrl
|
||||
)
|
||||
}
|
||||
}
|
||||
40
src/main/kotlin/de/wulkanat/web/Parser.kt
Normal file
40
src/main/kotlin/de/wulkanat/web/Parser.kt
Normal file
@@ -0,0 +1,40 @@
|
||||
package de.wulkanat.web
|
||||
|
||||
import de.wulkanat.extensions.absUrl
|
||||
import de.wulkanat.extensions.get
|
||||
import de.wulkanat.extensions.imgSrc
|
||||
import de.wulkanat.extensions.text
|
||||
import de.wulkanat.model.BlogPostPreview
|
||||
import de.wulkanat.model.JobListingPreview
|
||||
|
||||
private const val BLOG_POST_STATE_FILE_NAME = "blog_state.json"
|
||||
fun fakeUpdateBlogPost() = removeFirstFromSiteSave<BlogPostPreview>(BLOG_POST_STATE_FILE_NAME)
|
||||
fun getNewBlogPosts() = updateSite("https://hytale.com/news", BLOG_POST_STATE_FILE_NAME) { doc ->
|
||||
doc["postWrapper"].map {
|
||||
BlogPostPreview(
|
||||
title = it["post__details__heading"].text,
|
||||
imgUrl = it["post__image__frame"].first().imgSrc,
|
||||
fullPostUrl = it.absUrl,
|
||||
date = it["post__details__meta__date"].text,
|
||||
author = it["post__details__meta__author"].text,
|
||||
description = it["post__details__body"].text,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private const val JOB_LISTING_STATE_FILE_NAME = "jobs_state.json"
|
||||
fun fakeUpdateJobListings() = removeFirstFromSiteSave<JobListingPreview>(JOB_LISTING_STATE_FILE_NAME)
|
||||
fun getNewJobListings() = updateSite("https://hypixelstudios.com/jobs/", JOB_LISTING_STATE_FILE_NAME) { doc ->
|
||||
doc["current-jobs__departments"].flatMap { jobDepartment ->
|
||||
val jobDepartmentName = jobDepartment["current-jobs__department-name"].text
|
||||
|
||||
jobDepartment["current-jobs__job"].map { job ->
|
||||
JobListingPreview(
|
||||
title = job["current-jobs__job-title"].text,
|
||||
department = jobDepartmentName,
|
||||
location = job["current-jobs__job-location"].text,
|
||||
fullListingUrl = job.absUrl
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +1,37 @@
|
||||
package de.wulkanat.web
|
||||
|
||||
import de.wulkanat.Admin
|
||||
import de.wulkanat.DiscordRpc
|
||||
import de.wulkanat.model.BlogPostPreview
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
object SiteWatcher {
|
||||
private const val BLOG_INDEX_URL = "https://www.hytale.com/news"
|
||||
var newestBlog: BlogPostPreview? = null
|
||||
private var siteOnline = false
|
||||
/**
|
||||
* Removes the first element of a saved JSON list file
|
||||
*/
|
||||
inline fun <reified T>
|
||||
removeFirstFromSiteSave(fileName: String) = File(fileName).takeIf { it.exists() }?.let {
|
||||
it.writeText(Json.encodeToString(Json.decodeFromString<List<T>>(it.readText()).toMutableList().apply { removeFirst() }))
|
||||
}
|
||||
|
||||
fun hasNewBlogPost(): Boolean {
|
||||
try {
|
||||
val doc = Jsoup.connect(BLOG_INDEX_URL).get()
|
||||
val newBlog = BlogPostParser.getFistBlog(doc)
|
||||
inline fun <reified T> updateSite(url: String, fileName: String, parser: (Document) -> List<T>) = try {
|
||||
val currentStateFile = File(fileName)
|
||||
|
||||
if (newestBlog == newBlog) {
|
||||
return false
|
||||
}
|
||||
val retrievedElements = parser(Jsoup.connect(url).get())
|
||||
var currentElements = if (currentStateFile.exists())
|
||||
Json.decodeFromString(currentStateFile.readText()) else retrievedElements
|
||||
|
||||
if (newestBlog == null) {
|
||||
newestBlog = newBlog
|
||||
return false
|
||||
} else {
|
||||
newestBlog = newBlog
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Admin.error("Connection to Hytale Server failed", e.message ?: e.localizedMessage)
|
||||
siteOnline = false
|
||||
DiscordRpc.updatePresence(siteOnline)
|
||||
val newElements = retrievedElements - currentElements
|
||||
currentElements = retrievedElements
|
||||
currentStateFile.writeText(Json.encodeToString(currentElements))
|
||||
|
||||
return false
|
||||
}
|
||||
newElements
|
||||
} catch (e: IOException) {
|
||||
// TODO: put this somewhere else
|
||||
// Admin.error("""Fetching "$url" failed!""", e.message ?: e.localizedMessage)
|
||||
// DiscordRpc.updatePresence(canUpdate.also { canUpdate = false })
|
||||
|
||||
if (!siteOnline) {
|
||||
siteOnline = true
|
||||
DiscordRpc.updatePresence(siteOnline)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user