Code Sketch
yoi steal an egg
Category: Programming
// STEAL AN EGG - LIVE SPAWN RADAR
// Paste this whole script directly into the Kojo Script Editor and press RUN.
// Important: this is intentionally a top-level Kojo script, NOT an unused object/main wrapper.
import java.awt.BorderLayout
import java.awt.Color
import java.awt.Desktop
import java.awt.Dimension
import java.awt.FlowLayout
import java.awt.Font
import java.awt.GridLayout
import java.awt.Toolkit
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import java.awt.event.WindowAdapter
import java.awt.event.WindowEvent
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.StringReader
import java.net.HttpURLConnection
import java.net.URL
import java.nio.charset.StandardCharsets
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import javax.swing.BorderFactory
import javax.swing.JButton
import javax.swing.JComboBox
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.JPanel
import javax.swing.JScrollPane
import javax.swing.JTable
import javax.swing.JTextField
import javax.swing.SwingConstants
import javax.swing.SwingUtilities
import javax.swing.Timer
import javax.swing.UIManager
import javax.swing.WindowConstants
import javax.swing.event.DocumentEvent
import javax.swing.event.DocumentListener
import javax.swing.table.DefaultTableModel
import javax.swing.text.MutableAttributeSet
import javax.swing.text.html.HTML
import javax.swing.text.html.HTMLEditorKit
import javax.swing.text.html.parser.ParserDelegator
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
SwingUtilities.invokeLater(new Runnable {
override def run(): Unit = {
// ---------- Colours and window ----------
val bg = new Color(12, 17, 31)
val panel = new Color(22, 30, 51)
val panel2 = new Color(29, 39, 65)
val white = new Color(240, 244, 255)
val muted = new Color(166, 180, 207)
val green = new Color(88, 225, 146)
val yellow = new Color(255, 210, 95)
val red = new Color(255, 122, 122)
try UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName) catch { case _: Exception => () }
val frame = new JFrame("STEAL AN EGG - LIVE SPAWN RADAR")
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE)
frame.setSize(1080, 700)
frame.setMinimumSize(new Dimension(850, 570))
val root = new JPanel(new BorderLayout(12, 12))
root.setBackground(bg)
root.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15))
// ---------- Header ----------
val header = new JPanel(new BorderLayout(5, 5))
header.setBackground(panel)
header.setBorder(BorderFactory.createEmptyBorder(16, 18, 14, 18))
val heading = new JLabel("STEAL AN EGG / LIVE SPAWN RADAR")
heading.setForeground(white)
heading.setFont(new Font("SansSerif", Font.BOLD, 24))
val subheading = new JLabel("Latest public Secret, Eternal and Divine spawn reports")
subheading.setForeground(muted)
subheading.setFont(new Font("SansSerif", Font.PLAIN, 13))
header.add(heading, BorderLayout.NORTH)
header.add(subheading, BorderLayout.SOUTH)
// ---------- Summary cards ----------
val latestValue = new JLabel("Waiting for reports", SwingConstants.CENTER)
val countValue = new JLabel("0", SwingConstants.CENTER)
val refreshValue = new JLabel("60 sec", SwingConstants.CENTER)
def makeCard(caption: String, value: JLabel): JPanel = {
val p = new JPanel(new BorderLayout(5, 8))
p.setBackground(panel2)
p.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(new Color(48, 61, 88)),
BorderFactory.createEmptyBorder(10, 12, 10, 12)
))
val t = new JLabel(caption, SwingConstants.CENTER)
t.setForeground(muted)
t.setFont(new Font("SansSerif", Font.BOLD, 11))
value.setForeground(white)
value.setFont(new Font("SansSerif", Font.BOLD, 17))
p.add(t, BorderLayout.NORTH)
p.add(value, BorderLayout.CENTER)
p
}
val cards = new JPanel(new GridLayout(1, 3, 10, 0))
cards.setOpaque(false)
cards.add(makeCard("LATEST REPORTED PET", latestValue))
cards.add(makeCard("REPORTS SHOWN", countValue))
cards.add(makeCard("NEXT CHECK", refreshValue))
val north = new JPanel(new BorderLayout(0, 10))
north.setOpaque(false)
north.add(header, BorderLayout.NORTH)
north.add(cards, BorderLayout.SOUTH)
root.add(north, BorderLayout.NORTH)
// ---------- Filters ----------
val searchField = new JTextField(20)
searchField.setFont(new Font("SansSerif", Font.PLAIN, 13))
searchField.setToolTipText("Search pet or biome")
val rarityBox = new JComboBox[String](Array[String]("All rarities", "Secret", "Eternal", "Divine"))
rarityBox.setFont(new Font("SansSerif", Font.PLAIN, 12))
val filterPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 6))
filterPanel.setBackground(panel)
val searchLabel = new JLabel("Search pet / biome:")
searchLabel.setForeground(white)
val rarityLabel = new JLabel("Rarity:")
rarityLabel.setForeground(white)
filterPanel.add(searchLabel)
filterPanel.add(searchField)
filterPanel.add(rarityLabel)
filterPanel.add(rarityBox)
// ---------- Results table ----------
val columns = Array[AnyRef]("PET", "RARITY", "BIOME / LOCATION", "REPORTED AT (UTC)", "REPORTED AT (IST)")
val model = new DefaultTableModel(columns, 0) {
override def isCellEditable(row: Int, column: Int): Boolean = false
}
val table = new JTable(model)
table.setFont(new Font("SansSerif", Font.PLAIN, 13))
table.setRowHeight(30)
table.setForeground(white)
table.setBackground(new Color(18, 25, 43))
table.setGridColor(new Color(48, 61, 88))
table.setSelectionBackground(new Color(49, 76, 120))
table.setSelectionForeground(Color.WHITE)
table.getTableHeader.setFont(new Font("SansSerif", Font.BOLD, 12))
table.getTableHeader.setBackground(new Color(37, 51, 81))
table.getTableHeader.setForeground(white)
table.setFillsViewportHeight(true)
table.setAutoCreateRowSorter(true)
val scroll = new JScrollPane(table)
scroll.setBorder(BorderFactory.createLineBorder(new Color(48, 61, 88)))
scroll.getViewport.setBackground(new Color(18, 25, 43))
val center = new JPanel(new BorderLayout(0, 8))
center.setOpaque(false)
center.add(filterPanel, BorderLayout.NORTH)
center.add(scroll, BorderLayout.CENTER)
root.add(center, BorderLayout.CENTER)
// ---------- Footer and buttons ----------
val status = new JLabel("Status: Window opened. Connecting to public report source?")
status.setForeground(yellow)
status.setFont(new Font("SansSerif", Font.BOLD, 12))
val cacheTime = new JLabel("Source cache time: not checked yet")
cacheTime.setForeground(muted)
cacheTime.setFont(new Font("SansSerif", Font.PLAIN, 11))
val note = new JLabel("Community reports only. They may be delayed and may belong to another Roblox server; this cannot predict the next random egg.")
note.setForeground(yellow)
note.setFont(new Font("SansSerif", Font.PLAIN, 11))
val refreshButton = new JButton("REFRESH NOW")
val soundButton = new JButton("SOUND: ON")
val openButton = new JButton("OPEN LIVE WEBSITE")
val buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT, 8, 0))
buttons.setOpaque(false)
buttons.add(soundButton)
buttons.add(openButton)
buttons.add(refreshButton)
val footerLabels = new JPanel(new GridLayout(3, 1, 0, 3))
footerLabels.setOpaque(false)
footerLabels.add(status)
footerLabels.add(cacheTime)
footerLabels.add(note)
val footer = new JPanel(new BorderLayout(8, 5))
footer.setOpaque(false)
footer.add(footerLabels, BorderLayout.CENTER)
footer.add(buttons, BorderLayout.EAST)
root.add(footer, BorderLayout.SOUTH)
// ---------- Report reader ----------
case class SpawnRecord(pet: String, rarity: String, biome: String, utc: String) {
def key: String = pet + "|" + rarity + "|" + biome + "|" + utc
}
case class SpawnPage(records: Vector[SpawnRecord], savedAt: String)
class SpawnParser extends HTMLEditorKit.ParserCallback {
val rows = ArrayBuffer[List[String]]()
val allText = new StringBuilder
private var currentRow = ArrayBuffer[String]()
private var cell: java.lang.StringBuilder = null
override def handleStartTag(tag: HTML.Tag, attrs: MutableAttributeSet, pos: Int): Unit = {
if (tag == HTML.Tag.TR) currentRow = ArrayBuffer[String]()
if (tag == HTML.Tag.TD || tag == HTML.Tag.TH) cell = new java.lang.StringBuilder
}
override def handleSimpleTag(tag: HTML.Tag, attrs: MutableAttributeSet, pos: Int): Unit = {
if (tag == HTML.Tag.BR && cell != null) cell.append(' ')
}
override def handleText(data: Array[Char], pos: Int): Unit = {
val s = new String(data)
allText.append(s).append(' ')
if (cell != null) cell.append(s).append(' ')
}
override def handleEndTag(tag: HTML.Tag, pos: Int): Unit = {
if ((tag == HTML.Tag.TD || tag == HTML.Tag.TH) && cell != null) {
currentRow += cell.toString.replaceAll("\\s+", " ").trim
cell = null
}
if (tag == HTML.Tag.TR && currentRow.nonEmpty) rows += currentRow.toList
}
}
def cleanText(s: String): String = Option(s).getOrElse("").replace('\u00a0', ' ').replaceAll("\\s+", " ").trim
def readReports(): SpawnPage = {
val address = "https://www.stealegg.com/api/live-history.php?lang=en"
val connection = new URL(address).openConnection().asInstanceOf[HttpURLConnection]
connection.setRequestMethod("GET")
connection.setConnectTimeout(10000)
connection.setReadTimeout(12000)
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; KojoStealEggRadar/1.0)")
connection.setRequestProperty("Accept", "text/html")
var reader: BufferedReader = null
try {
val code = connection.getResponseCode
if (code < 200 || code >= 300) throw new RuntimeException("Website returned HTTP " + code)
reader = new BufferedReader(new InputStreamReader(connection.getInputStream, StandardCharsets.UTF_8))
val html = new StringBuilder
var line = reader.readLine()
while (line != null) {
html.append(line).append('\n')
line = reader.readLine()
}
val parser = new SpawnParser
new ParserDelegator().parse(new StringReader(html.toString), parser, true)
val timePattern = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}".r
val rarityPattern = "(?i)\\b(Secret|Eternal|Divine)\\b".r
val records = parser.rows.flatMap { row =>
if (row.length >= 3 && timePattern.findFirstIn(row(2)).isDefined) {
val rawPet = cleanText(row(0))
val rarity = rarityPattern.findFirstMatchIn(rawPet).map(_.group(1)).getOrElse("Unknown")
val pet = cleanText(rarityPattern.replaceAllIn(rawPet, ""))
val biome = cleanText(row(1))
val reported = cleanText(row(2))
if (pet.nonEmpty && biome.nonEmpty) Some(SpawnRecord(pet, rarity, biome, reported)) else None
} else None
}.toVector
if (records.isEmpty) throw new RuntimeException("The source responded, but no report rows were found. The website format may have changed.")
val cachePattern = "(?i)Cache\\s+saved:\\s*(\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}:\\d{2})\\s*UTC".r
val saved = cachePattern.findFirstMatchIn(parser.allText.toString).map(_.group(1)).getOrElse("Not shown")
SpawnPage(records, saved)
} finally {
if (reader != null) try reader.close() catch { case _: Exception => () }
connection.disconnect()
}
}
// ---------- Filtering and refresh ----------
var allRecords = Vector.empty[SpawnRecord]
val seen = mutable.Set[String]()
var firstLoad = true
var loading = false
var soundEnabled = true
var secondsLeft = 60
def utcToIndia(value: String): String = {
try {
val fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
val utcTime = LocalDateTime.parse(value, fmt).atZone(ZoneId.of("UTC"))
utcTime.withZoneSameInstant(ZoneId.of("Asia/Kolkata")).format(DateTimeFormatter.ofPattern("dd MMM HH:mm:ss"))
} catch { case _: Exception => "-" }
}
def applyFilters(): Unit = {
val query = cleanText(searchField.getText).toLowerCase
val chosen = String.valueOf(rarityBox.getSelectedItem)
val filtered = allRecords.filter { r =>
val matchText = query.isEmpty || r.pet.toLowerCase.contains(query) || r.biome.toLowerCase.contains(query)
val matchRarity = chosen == "All rarities" || r.rarity.equalsIgnoreCase(chosen)
matchText && matchRarity
}
model.setRowCount(0)
filtered.foreach { r =>
model.addRow(Array[AnyRef](r.pet, r.rarity, r.biome, r.utc + " UTC", utcToIndia(r.utc) + " IST"))
}
countValue.setText(filtered.length + " / " + allRecords.length)
}
def refreshReports(): Unit = {
if (loading) return
loading = true
status.setText("Status: Checking public report history?")
status.setForeground(yellow)
refreshButton.setEnabled(false)
val worker = new Thread(new Runnable {
override def run(): Unit = {
var page: SpawnPage = null
var problem: String = null
try page = readReports() catch { case ex: Exception => problem = Option(ex.getMessage).getOrElse(ex.getClass.getSimpleName) }
SwingUtilities.invokeLater(new Runnable {
override def run(): Unit = {
loading = false
refreshButton.setEnabled(true)
secondsLeft = 60
if (problem != null) {
status.setText("Status: Could not load reports ? " + problem)
status.setForeground(red)
} else {
val newRows = if (firstLoad) Vector.empty[SpawnRecord] else page.records.filterNot(r => seen.contains(r.key))
page.records.foreach(r => seen += r.key)
firstLoad = false
allRecords = page.records
applyFilters()
val latest = page.records.head
latestValue.setText("<html><center>" + latest.pet + "<br><font size='3'>" + latest.rarity + " / " + latest.biome + "</font></center></html>")
cacheTime.setText("Source cache saved: " + page.savedAt + " UTC | Last checked: " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")))
if (newRows.nonEmpty) {
status.setText("Status: New community report(s): " + newRows.take(3).map(_.pet).mkString(", "))
status.setForeground(green)
if (soundEnabled) Toolkit.getDefaultToolkit.beep()
} else {
status.setText("Status: Connected ? latest " + page.records.length + " public reports loaded")
status.setForeground(green)
}
}
}
})
}
}, "StealEggRadarFetch")
worker.setDaemon(true)
worker.start()
}
val filterListener = new DocumentListener {
override def insertUpdate(e: DocumentEvent): Unit = applyFilters()
override def removeUpdate(e: DocumentEvent): Unit = applyFilters()
override def changedUpdate(e: DocumentEvent): Unit = applyFilters()
}
searchField.getDocument.addDocumentListener(filterListener)
rarityBox.addActionListener(new ActionListener {
override def actionPerformed(e: ActionEvent): Unit = applyFilters()
})
refreshButton.addActionListener(new ActionListener {
override def actionPerformed(e: ActionEvent): Unit = refreshReports()
})
soundButton.addActionListener(new ActionListener {
override def actionPerformed(e: ActionEvent): Unit = {
soundEnabled = !soundEnabled
soundButton.setText(if (soundEnabled) "SOUND: ON" else "SOUND: OFF")
}
})
openButton.addActionListener(new ActionListener {
override def actionPerformed(e: ActionEvent): Unit = {
try {
val liveUrl = new URL("https://www.stealegg.com/en/live/")
if (Desktop.isDesktopSupported && Desktop.getDesktop.isSupported(Desktop.Action.BROWSE)) {
Desktop.getDesktop.browse(liveUrl.toURI)
} else {
status.setText("Open this page in your browser: https://www.stealegg.com/en/live/")
status.setForeground(yellow)
}
} catch {
case ex: Exception =>
status.setText("Could not open browser: " + Option(ex.getMessage).getOrElse("unknown error"))
status.setForeground(red)
}
}
})
val countdown = new Timer(1000, new ActionListener {
override def actionPerformed(e: ActionEvent): Unit = {
secondsLeft -= 1
if (secondsLeft <= 0) {
secondsLeft = 60
refreshReports()
}
refreshValue.setText(secondsLeft + " sec")
}
})
// ---------- Show the actual UI BEFORE the first internet request ----------
frame.setContentPane(root)
frame.setSize(1080, 700)
frame.setLocationRelativeTo(null)
frame.setVisible(true)
frame.toFront()
countdown.start()
refreshReports()
frame.addWindowListener(new WindowAdapter {
override def windowClosed(e: WindowEvent): Unit = countdown.stop()
})
}
})