Skip to content
This repository has been archived by the owner on Dec 12, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' into genres
Browse files Browse the repository at this point in the history
  • Loading branch information
Xerus committed Sep 16, 2018
2 parents 2f8e685 + 5fe6419 commit 9e6eb20
Show file tree
Hide file tree
Showing 23 changed files with 324 additions and 220 deletions.
36 changes: 30 additions & 6 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,55 @@ Browse, stream and download Monstercat Songs, powered by the Monstercat API and

## Usage

[Download](http://monsterutilities.bplaced.net/downloads?download)
[Download](http://monsterutilities.bplaced.net/downloads?download) or use the GitHub releases.

> This is a pre-Release, you may encounter bugs.
If you do, open an issue here or send feedback from inside the application.
The latter will automatically include logs, which reside in `TEMP/monsterutilities/logs`

To run it, you need to have Java 8 by Oracle installed on your computer.

Read the initial guide and follow the tooltips. Improved user-friendliness is in development ;)
Read the initial guide and follow the tooltips.
Improved user-friendliness is in development ;)

### Troubleshooting

#### connect.sid

For downloading and listening to the latest Track, your `connect.sid`
needs to be entered in the bottom of the Downloader. It is a cookie that
identifies your Monstercat Account. Here's how to obtain it:

1) Log in on [monstercat.com](https://monstercat.com) and ensure that you have a valid Monstercat Gold subscription
2) Go to your browser cookies and search for `connect.monstercat.com`
[Quick link for Chrome](chrome://settings/cookies/detail?site=connect.monstercat.com)
3) Find the content of `connect.sid`. It is a string starting with `s%3A` and has around 90 characters.
4) Copy that string into the `connect.sid` Textfield at the bottom of the Downloader.

#### Downloader

Sometimes, the cache runs into issues and that may contribute to issues in the Downloader.
Simply disable the cache, restart the application and enable it again.

> If you still have issues - no problem!
> Hit me up on [Discord](https://discord.gg/ZEusvHS) or send Feedback directly from the application!
## Screenshots

### Catalog

The Catalog provides an overview of all Tracks ever released on the label and extensive possibilities of filtering them.
The Catalog provides an overview of all Tracks ever released on the label and
extensive possibilities of filtering them.
> Tip: You can customize which columns to show by clicking on the `+` in the top right
![Catalog](assets/screenshots/catalog.png)
![Catalog filtering](assets/screenshots/filtering.png)

### Streaming

In case you missed it in the other Screenshots: There's a player on top that can stream any Monstercat track,
just like the website. Double-click on any piece in the Catalog or Downloader to load it into the Player!

In case you missed it in the other Screenshots:
There's a player on top that can stream any Monstercat track, just like the website.
Double-click on any piece in the Catalog or Downloader to load it into the Player!
![Player](assets/screenshots/player.png)

### Downloader
Expand Down
30 changes: 15 additions & 15 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ version = "dev" + Scanner(Runtime.getRuntime().exec("git rev-list --count HEAD")
file("src/resources/version").writeText(version as String)

plugins {
kotlin("jvm") version "1.2.61"
kotlin("jvm") version "1.2.70"
application
id("com.github.johnrengelman.shadow") version "2.0.4"
id("com.github.ben-manes.versions") version "0.19.0"
id("com.github.ben-manes.versions") version "0.20.0"
}

// source directories
Expand Down Expand Up @@ -47,19 +47,19 @@ repositories {
}

dependencies {
compile("com.github.Xerus2000", "util", "master-SNAPSHOT")
compile(kotlin("stdlib-jdk8"))
compile(kotlin("reflect"))
implementation(kotlin("reflect"))

compile("org.controlsfx", "controlsfx", "8.40.14")
implementation("com.github.Xerus2000.util", "javafx", "-SNAPSHOT")
implementation("org.controlsfx", "controlsfx", "8.40.14")

compile("be.bluexin", "drpc4k", "0.6-SNAPSHOT")
implementation("ch.qos.logback", "logback-classic", "1.2.3")
implementation("com.github.Xerus2000", "drpc4k", "-SNAPSHOT")
implementation("org.apache.httpcomponents", "httpmime", "4.5.+")
implementation("com.google.apis", "google-api-services-sheets", "v4-rev542-1.25.0")

compile("org.apache.httpcomponents", "httpmime", "4.5.5")
compile("com.google.apis", "google-api-services-sheets", "v4-rev527-1.23.0")

testCompile("org.junit.jupiter", "junit-jupiter-api", "5.2.0")
testRuntimeOnly("org.junit.jupiter", "junit-jupiter-engine", "5.2.0")
val junitVersion = "5.3.1"
testCompile("org.junit.jupiter", "junit-jupiter-api", junitVersion)
testRuntimeOnly("org.junit.jupiter", "junit-jupiter-engine", junitVersion)
}

val file
Expand All @@ -73,8 +73,8 @@ tasks {

"run"(JavaExec::class) {
group = MAIN
// Usage: gradle run -Dargs="FINE save"
args = System.getProperty("args", "").split(" ")
// Usage: gradle run -Dargs="--loglevel trace"
args = System.getProperty("args", "--loglevel debug").split(" ")
}

"shadowJar"(ShadowJar::class) {
Expand Down Expand Up @@ -112,7 +112,7 @@ tasks {
setDelete(file(".").listFiles { f -> f.name.run { startsWith("MonsterUtilities-") && endsWith("jar") && this != file } })
}

"test"(Test::class) {
withType<Test> {
useJUnitPlatform()
}

Expand Down
2 changes: 1 addition & 1 deletion src/archive/Downloader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class DownloaderSwing : BasePanel() {
}

init {
launch {
GlobalScope.launch {
logger.fine("DownloadWorker started")

var limit = LIMIT.int
Expand Down
92 changes: 92 additions & 0 deletions src/main/xerus/monstercat/Logging.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package xerus.monstercat

import ch.qos.logback.classic.Level
import ch.qos.logback.classic.LoggerContext
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
import ch.qos.logback.classic.filter.LevelFilter
import ch.qos.logback.classic.filter.ThresholdFilter
import ch.qos.logback.classic.spi.Configurator
import ch.qos.logback.classic.spi.ILoggingEvent
import ch.qos.logback.core.ConsoleAppender
import ch.qos.logback.core.FileAppender
import ch.qos.logback.core.rolling.RollingFileAppender
import ch.qos.logback.core.spi.ContextAwareBase
import kotlinx.coroutines.experimental.GlobalScope
import kotlinx.coroutines.experimental.launch
import mu.KotlinLogging
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import xerus.ktutil.currentSeconds
import xerus.ktutil.getStackTraceString
import java.io.File

private val logDir: File
get() = cacheDir.resolve("logs").apply { mkdirs() }
private val logFile = logDir.resolve("log${currentSeconds()}.txt")
private var logLevel: Level = Level.WARN

internal fun initLogging(args: Array<String>) {
args.indexOf("--loglevel").takeIf { it > -1 }?.let {
logLevel = args.getOrNull(it + 1)?.let { Level.toLevel(it, null) } ?: run {
println("WARNING: Loglevel argument given without a valid value! Use one of {OFF, ERROR, WARN, INFO, DEBUG, TRACE, ALL}")
return@let
}
}
Thread.setDefaultUncaughtExceptionHandler { thread, ex ->
LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME).warn("Uncaught exception in $thread: ${ex.getStackTraceString()}")
}
val logger = KotlinLogging.logger { }
logger.info("Console loglevel: $logLevel")
logger.info("Logging to $logFile")
GlobalScope.launch {
val logs = logDir.listFiles()
if (logs.size > 10) {
logs.asSequence().sortedByDescending { it.name }.drop(5).filter {
val timestamp = it.nameWithoutExtension.substring(3).toIntOrNull() ?: return@filter true
timestamp + 200_000 < currentSeconds()
}.also {
val count = it.count()
if (count > 0)
logger.debug("Deleting $count old logs")
}.forEach { it.delete() }
}
}
}

internal class LogbackConfigurator : ContextAwareBase(), Configurator {

override fun configure(lc: LoggerContext) {

val encoder = PatternLayoutEncoder().apply {
context = lc
pattern = "%d{HH:mm:ss} [%-25.25thread] %-5level %-30logger{30} %msg%n"
start()
}

val consoleAppender = ConsoleAppender<ILoggingEvent>().apply {
name = "console"
context = lc
this.encoder = encoder
addFilter(ThresholdFilter().apply {
setLevel(logLevel.toString())
start()
})
start()
}

val fileAppender = FileAppender<ILoggingEvent>().apply {
name = "file"
file = logFile.toString()
context = lc
this.encoder = encoder
start()
}

val rootLogger = lc.getLogger(Logger.ROOT_LOGGER_NAME)
if(logLevel.levelInt < Level.DEBUG_INT)
rootLogger.level = logLevel
rootLogger.addAppender(consoleAppender)
rootLogger.addAppender(fileAppender)
}

}
72 changes: 28 additions & 44 deletions src/main/xerus/monstercat/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,76 +4,60 @@ import com.google.api.client.googleapis.auth.oauth2.GoogleCredential
import com.google.api.services.sheets.v4.SheetsScopes
import javafx.scene.Scene
import javafx.scene.image.Image
import kotlinx.coroutines.experimental.asCoroutineDispatcher
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import xerus.ktutil.*
import kotlinx.coroutines.experimental.*
import mu.KotlinLogging
import xerus.ktutil.SystemUtils
import xerus.ktutil.getResource
import xerus.ktutil.javafx.applySkin
import xerus.ktutil.javafx.ui.App
import xerus.ktutil.ui.SimpleFrame
import java.io.File
import java.net.URL
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.ThreadFactory
import java.util.concurrent.atomic.AtomicInteger
import javax.swing.JTextArea

typealias logger = XerusLogger

val VERSION = getResource("version")!!.readText()
val isUnstable = VERSION.contains('-')

val logDir: File
get() = cacheDir.resolve("logs").apply { mkdirs() }
val cacheDir: File
get() = (File("/var/tmp").takeIf { it.exists() } ?: File(System.getProperty("java.io.tmpdir")))
.resolve("monsterutilities").apply { mkdirs() }

lateinit var monsterUtilities: MonsterUtilities

val globalThreadPool: ExecutorService = Executors.newCachedThreadPool()
val globalThreadPool: ExecutorService = Executors.newCachedThreadPool(object : ThreadFactory {
private val poolNumber = AtomicInteger(1)
override fun newThread(r: Runnable) =
Thread(Thread.currentThread().threadGroup, r, "global-" + poolNumber.getAndIncrement())
})
val globalDispatcher = globalThreadPool.asCoroutineDispatcher()

val location: URL = MonsterUtilities::class.java.protectionDomain.codeSource.location
var checkUpdate = Settings.AUTOUPDATE() && location.toString().endsWith(".jar")
val jarLocation: URL = MonsterUtilities::class.java.protectionDomain.codeSource.location

fun main(args: Array<String>) {
XerusLogger.parseArgs(*args, defaultLevel = "finer")
if (args.contains("--no-update"))
checkUpdate = false
Thread.setDefaultUncaughtExceptionHandler { thread, ex ->
logger.warning("Uncaught exception in $thread: ${ex.getStackTraceString()}")
}
val logfile = logDir.resolve("log${currentSeconds()}.txt")
try {
XerusLogger.logToFile(logfile)
logger.config("Logging to $logfile")
launch {
val logs = logDir.listFiles()
if (logs.size > 10) {
logs.asSequence().sortedByDescending { it.name }.drop(5).filter {
val timestamp = it.nameWithoutExtension.substring(3).toIntOrNull() ?: return@filter true
timestamp + 200_000 < currentSeconds()
}.also {
val count = it.count()
if (count > 0)
logger.finer("Deleting $count old logs")
}.forEach { it.delete() }
}
}
} catch (t: Throwable) {
showErrorSafe(t, "Can't log to $logfile!")
}
if (!javaVersion().startsWith("1.8")) {
SimpleFrame { add(JTextArea("Please install and use Java 8!\nThe current version is ${javaVersion()}").apply { isEditable = false }) }
initLogging(args)
val logger = KotlinLogging.logger {}

if (!SystemUtils.javaVersion.startsWith("1.8")) {
SimpleFrame { add(JTextArea("Please install and use Java 8!\nThe current version is ${SystemUtils.javaVersion}").apply { isEditable = false }) }
return
}
logger.info("Version: $VERSION, Java version: ${javaVersion()}")
logger.config("Initializing Google Sheets API Service")
logger.info("Version: $VERSION, Java version: ${SystemUtils.javaVersion}")

logger.info("Initializing Google Sheets API Service")
Sheets.initService("MonsterUtilities", GoogleCredential().createScoped(listOf(SheetsScopes.SPREADSHEETS_READONLY)))

val checkUpdate = !args.contains("--no-update") && Settings.AUTOUPDATE() && jarLocation.toString().endsWith(".jar")
App.launch("MonsterUtilities $VERSION", { stage ->
stage.icons.addAll(arrayOf("img/icon64.png").map {
getResource(it)?.let { Image(it.toExternalForm()) }
?: null.apply { logger.warning("Resource $it not found") }
?: null.apply { logger.warn("Resource $it not found!") }
})
}, {
val scene = Scene(MonsterUtilities(), 800.0, 700.0)
val scene = Scene(MonsterUtilities(checkUpdate), 800.0, 700.0)
scene.applySkin(Settings.SKIN())
scene
})
Expand All @@ -82,7 +66,7 @@ fun main(args: Array<String>) {
}

fun showErrorSafe(error: Throwable, title: String = "Error") {
launch {
GlobalScope.launch {
var i = 0
while (i < 100 && !::monsterUtilities.isInitialized) {
delay(200)
Expand Down
Loading

0 comments on commit 9e6eb20

Please sign in to comment.