From ab787900cfc379c2d3d229440f0db860efb332e8 Mon Sep 17 00:00:00 2001 From: Isaac Parenteau Date: Sun, 6 Oct 2019 14:29:14 -0500 Subject: [PATCH 1/4] started migrating to a database --- pom.xml | 254 +++++++++++++++--- .../eighttrack/handlers/Mp3UploadHandler.java | 60 +++++ .../eighttrack/handlers/Mp3UploadResults.java | 15 ++ .../{Entry.java => EightTrackLauncher.java} | 11 +- .../Tables/V01_000_000__initial_tables.sql | 8 + .../migration/mariadb/afterMigrate.sql | 34 +++ 6 files changed, 349 insertions(+), 33 deletions(-) create mode 100644 src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadHandler.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadResults.java rename src/main/java/net/locusworks/discord/eighttrack/main/{Entry.java => EightTrackLauncher.java} (84%) create mode 100644 src/main/resources/database/migration/mariadb/Tables/V01_000_000__initial_tables.sql create mode 100644 src/main/resources/database/migration/mariadb/afterMigrate.sql diff --git a/pom.xml b/pom.xml index 4831a91..6e99497 100644 --- a/pom.xml +++ b/pom.xml @@ -18,11 +18,18 @@ - 2.11.2 - 1.7.26 - http://nexus.locusworks.net + 6.0.3 + 2.4.4 + 5.4.4.Final + 5.1.9.RELEASE + 2.1.8.RELEASE + 2.1.10.RELEASE + 2.12.1 + 1.7.28 + 3.0.0-M2 5.2.2 3.0 + http://nexus.locusworks.net @@ -64,33 +71,18 @@ - org.apache.maven.plugins - maven-shade-plugin - 3.2.1 + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} - package - shade + repackage - EightTrack-${project.version} - - - net.locusworks.discord.eighttrack.main.Entry - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - + EightTrackApp + JAR + @@ -118,21 +110,78 @@ + + org.flywaydb + flyway-maven-plugin + ${flyway.version} + + jdbc:mariadb://devops.locusworks.net:3306/ + false + + eighttrack + + _flyway_migration
+ + filesystem:${basedir}/src/main/resources/database/migration + +
+ + + + org.mariadb.jdbc + mariadb-java-client + ${mariadb.version} + + +
- - net.dv8tion - JDA - 4.0.0_46 + net.locusworks + applogger + 1.0.3-RELEASE net.locusworks - applogger - 1.0.1-RELEASE + crypto + 1.0.3-RELEASE + + + + org.apache.tika + tika-core + 1.22 + + + + org.apache.tika + tika-parsers + 1.22 + + + + + net.dv8tion + JDA + 4.0.0_47 + + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-databind + + @@ -141,6 +190,149 @@ 1.3.22 + + + org.flywaydb + flyway-core + ${flyway.version} + + + + org.mariadb.jdbc + mariadb-java-client + ${mariadb.version} + + + + + mysql + mysql-connector-java + 8.0.17 + + + + org.hibernate + hibernate-entitymanager + ${hibernate.version} + + + + + org.apache.commons + commons-dbcp2 + 2.7.0 + + + + + + org.springframework.boot + spring-boot + ${spring.boot.version} + + + org.springframework + spring-context + + + org.springframework + spring-core + + + org.hibernate + hibernate-core + + + + + + + org.springframework.boot + spring-boot-autoconfigure + ${spring.boot.version} + + + + + org.springframework + spring-core + ${spring.version} + + + org.springframework + spring-aop + ${spring.version} + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-jdbc + ${spring.version} + + + org.springframework + spring-tx + ${spring.version} + + + org.springframework.data + spring-data-jpa + ${spring.data.version} + + + + + javax.annotation + javax.annotation-api + 1.3.2 + + + + + com.fasterxml.jackson.core + jackson-core + 2.10.0.pr3 + + + + + com.fasterxml.jackson.core + jackson-databind + 2.10.0.pr3 + + + + + com.fasterxml.jackson.core + jackson-annotations + 2.10.0.pr3 + + + + javax.xml.bind + jaxb-api + 2.2.11 + + + com.sun.xml.bind + jaxb-core + 2.2.11 + + + com.sun.xml.bind + jaxb-impl + 2.2.11 + + + javax.activation + activation + 1.1.1 + + diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadHandler.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadHandler.java new file mode 100644 index 0000000..294ae90 --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadHandler.java @@ -0,0 +1,60 @@ +package net.locusworks.discord.eighttrack.handlers; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.apache.tika.exception.TikaException; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.parser.ParseContext; +import org.apache.tika.parser.mp3.LyricsHandler; +import org.apache.tika.parser.mp3.Mp3Parser; +import org.apache.tika.sax.BodyContentHandler; +import org.xml.sax.SAXException; + +public class Mp3UploadHandler { + + private Path file; + + public Mp3UploadHandler(Path file) { + this.file = file; + } + + public void parse() throws IOException, SAXException, TikaException { + + InputStream is = Files.newInputStream(file); + + BodyContentHandler handler = new BodyContentHandler(); + Metadata metadata = new Metadata(); + ParseContext context = new ParseContext(); + + Mp3Parser parser = new Mp3Parser(); + + parser.parse(is, handler, metadata, context); + + LyricsHandler lyrics = new LyricsHandler(is, handler); + + while(lyrics.hasLyrics()) { + System.out.println(lyrics.toString()); + } + + System.out.println("Contents of the document:" + handler.toString()); + System.out.println("Metadata of the document:"); + String[] metadataNames = metadata.names(); + + for(String name : metadataNames) { + System.out.println(name + ": " + metadata.get(name)); + } + } + + public static void main(String args[]) throws IOException, SAXException, TikaException { + String file = "S:\\Music\\Alan Walker\\01 Diamond Heart.mp3"; + Path path = Paths.get(file); + + Mp3UploadHandler fuh = new Mp3UploadHandler(path); + fuh.parse(); + } + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadResults.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadResults.java new file mode 100644 index 0000000..138351e --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadResults.java @@ -0,0 +1,15 @@ +package net.locusworks.discord.eighttrack.handlers; + +import org.apache.tika.metadata.Metadata; + +public class Mp3UploadResults { + + public Mp3UploadResults( Metadata metadata) { + parseResults(metadata); + } + + private void parseResults(Metadata metadata) { + + } + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/main/Entry.java b/src/main/java/net/locusworks/discord/eighttrack/main/EightTrackLauncher.java similarity index 84% rename from src/main/java/net/locusworks/discord/eighttrack/main/Entry.java rename to src/main/java/net/locusworks/discord/eighttrack/main/EightTrackLauncher.java index 259ef27..1f2f2d7 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/main/Entry.java +++ b/src/main/java/net/locusworks/discord/eighttrack/main/EightTrackLauncher.java @@ -31,6 +31,10 @@ import java.io.IOException; import java.nio.file.Paths; import javax.security.auth.login.LoginException; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + import net.dv8tion.jda.api.AccountType; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; @@ -38,12 +42,15 @@ import net.locusworks.discord.eighttrack.adaptors.MusicListenerAdaptor; import net.locusworks.logger.ApplicationLogger; import net.locusworks.logger.ApplicationLoggerFactory; -public class Entry { +@SpringBootApplication(scanBasePackages = {"net.locusworks.discord.pseudobot"}) +@EnableAutoConfiguration +@EnableScheduling +public class EightTrackLauncher { public static void main(String[] args) throws LoginException, IOException { if (args.length < 1) throw new RuntimeException("no token provided"); - ApplicationLogger logger = ApplicationLoggerFactory.getLogger(Entry.class); + ApplicationLogger logger = ApplicationLoggerFactory.getLogger(EightTrackLauncher.class); logger.info("Starting Eight-Track"); JDA client = new JDABuilder(AccountType.BOT).setToken(args[0]).build(); diff --git a/src/main/resources/database/migration/mariadb/Tables/V01_000_000__initial_tables.sql b/src/main/resources/database/migration/mariadb/Tables/V01_000_000__initial_tables.sql new file mode 100644 index 0000000..6aa1706 --- /dev/null +++ b/src/main/resources/database/migration/mariadb/Tables/V01_000_000__initial_tables.sql @@ -0,0 +1,8 @@ +CREATE TABLE eighttrack.discord_guild ( + id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Auto increment primary key', + guild_id bigint(20) NOT NULL COMMENT 'id of the discord guild', + guild_name varchar(100) NOT NULL COMMENT 'name of the discord guild', + date_joined datetime DEFAULT NULL COMMENT 'date the guild joined', + PRIMARY KEY (id), + UNIQUE KEY guild_UN (guild_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Information about discord guild'; diff --git a/src/main/resources/database/migration/mariadb/afterMigrate.sql b/src/main/resources/database/migration/mariadb/afterMigrate.sql new file mode 100644 index 0000000..629d102 --- /dev/null +++ b/src/main/resources/database/migration/mariadb/afterMigrate.sql @@ -0,0 +1,34 @@ +USE pseudobot; + +DELIMITER $$ +CREATE PROCEDURE set_optimizer_switch_on() +BEGIN +IF SUBSTRING(@@version,1,3) = '5.7' THEN + SET optimizer_switch = 'derived_merge=on'; +END IF; +END;$$ + +CREATE PROCEDURE create_user() +BEGIN + DECLARE foo BIGINT DEFAULT 0; + SELECT COUNT(*) INTO foo FROM mysql.user WHERE User = 'eighttrackAdmin' and Host = 'localhost'; + IF foo = 0 THEN + CREATE USER 'eighttrackAdmin'@'localhost' IDENTIFIED BY 'eighttrackAdmin2017!'; + END IF; + SELECT COUNT(*) INTO foo FROM mysql.user WHERE User = 'eighttrackAdmin' and Host = '%'; + IF foo = 0 THEN + CREATE USER 'eighttrackAdmin'@'%' IDENTIFIED BY 'eighttrackAdmin2017!'; + END IF; +END ;$$ + +DELIMITER ; + +CALL set_optimizer_switch_on(); +DROP PROCEDURE set_optimizer_switch_on; + +CALL create_user(); +DROP PROCEDURE create_user; + +GRANT SELECT,INSERT,UPDATE,DELETE ON pseudobot.* TO 'eighttrackAdmin'@'localhost'; +GRANT SELECT,INSERT,UPDATE,DELETE ON pseudobot.* TO 'eighttrackAdmin'@'%'; +FLUSH PRIVILEGES; \ No newline at end of file From 55b38cd18405be00ca2ef94032820d79d6bf4f19 Mon Sep 17 00:00:00 2001 From: Isaac Parenteau Date: Sun, 6 Oct 2019 16:00:37 -0500 Subject: [PATCH 2/4] Updated --- .../adaptors/MusicListenerAdaptor.java | 41 ++++++++++++++++++- .../handlers/GuildMusicHandler.java | 36 ++++++++++++++-- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/locusworks/discord/eighttrack/adaptors/MusicListenerAdaptor.java b/src/main/java/net/locusworks/discord/eighttrack/adaptors/MusicListenerAdaptor.java index a5ca8f4..1a7113e 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/adaptors/MusicListenerAdaptor.java +++ b/src/main/java/net/locusworks/discord/eighttrack/adaptors/MusicListenerAdaptor.java @@ -29,8 +29,18 @@ package net.locusworks.discord.eighttrack.adaptors; import java.io.IOException; import java.nio.file.Path; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.locusworks.discord.eighttrack.handlers.GuildMusicHandler; @@ -43,13 +53,41 @@ public class MusicListenerAdaptor extends ListenerAdapter { private ApplicationLogger logger; private Map playerMap; + private JDA client; - public MusicListenerAdaptor(Path musicDir) throws IOException { + public MusicListenerAdaptor(Path musicDir, JDA client) throws IOException { this.logger = ApplicationLoggerFactory.getLogger(MusicListenerAdaptor.class); this.playerMap = new ConcurrentHashMap<>(); this.musicDir = musicDir; + this.client = client; + + ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + executor.scheduleWithFixedDelay(()->checkPlayers(), 1, 1, TimeUnit.MINUTES); + } + private void checkPlayers() { + logger.debug("Checking players to see if anyone is listening"); + OffsetDateTime now = OffsetDateTime.now(); + for(Iterator> iterator = playerMap.entrySet().iterator(); iterator.hasNext();) { + Entry entry = iterator.next(); + GuildMusicHandler gmh = entry.getValue(); + long guildId = entry.getKey(); + + OffsetDateTime lastPlayed = gmh.getLastPlayed(); + Duration duration = Duration.between(lastPlayed, now); + if (duration.getSeconds() > 300) { + Guild guild = client.getGuildById(guildId); + if (guild == null) { + iterator.remove(); + continue; + } + guild.getAudioManager().closeAudioConnection(); + iterator.remove(); + } + } + } + @Override public void onGuildMessageReceived(GuildMessageReceivedEvent event) { if (event.getAuthor().isBot()) return; @@ -66,6 +104,7 @@ public class MusicListenerAdaptor extends ListenerAdapter { playerMap.put(event.getGuild().getIdLong(), new GuildMusicHandler(musicDir)); } GuildMusicHandler gmh = playerMap.get(event.getGuild().getIdLong()); + gmh.accept((id) -> playerMap.remove(id)); String command = event.getMessage().getContentRaw().trim().toLowerCase(); switch (command) { diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java index 4da92be..177e862 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java @@ -33,6 +33,7 @@ import java.nio.file.Path; import java.time.OffsetDateTime; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; import java.util.stream.Collectors; import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; @@ -42,6 +43,8 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.entities.ChannelType; +import net.dv8tion.jda.api.entities.GuildChannel; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.VoiceChannel; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; @@ -58,12 +61,18 @@ public class GuildMusicHandler { private ApplicationLogger logger; private AudioPlayer player; private AtomicBoolean playing; + private Long voiceChannelId; + + private OffsetDateTime lastPlayed; + + private Consumer callback; public GuildMusicHandler(Path musicDir) throws IOException { this.logger = ApplicationLoggerFactory.getLogger(GuildMusicHandler.class); this.playing = new AtomicBoolean(false); this.musicDir = musicDir; - + this.lastPlayed = OffsetDateTime.now(); + this.apm = new DefaultAudioPlayerManager(); AudioSourceManagers.registerLocalSource(apm); @@ -74,6 +83,14 @@ public class GuildMusicHandler { indexFiles(); } + public OffsetDateTime getLastPlayed() { + return lastPlayed; + } + + public void accept(Consumer callback) { + this.callback = callback; + } + public void isPlaying(boolean playing) { this.playing.set(playing); } @@ -127,6 +144,15 @@ public class GuildMusicHandler { } public void next(GuildMessageReceivedEvent event) { + + GuildChannel gc = event.getGuild().getGuildChannelById(ChannelType.VOICE, voiceChannelId); + if (gc != null && gc.getMembers().size() == 1) { + event.getChannel().sendMessage("Going silent since no one is currently listening to the channel").queue(); + event.getGuild().getAudioManager().closeAudioConnection(); + if (callback != null) callback.accept(event.getGuild().getIdLong()); + return; + } + playing.set(false); stop(event); play(event); @@ -143,12 +169,14 @@ public class GuildMusicHandler { event.getChannel().sendMessage(String.format("<@%s> you are not in a voice channel to play music", event.getMember().getId())).queue(); return; } - + if (!event.getGuild().getSelfMember().hasPermission(vc, Permission.VOICE_CONNECT, Permission.VOICE_SPEAK)) { event.getChannel().sendMessage(String.format("<@%s>, I cannot play my music in channel %s as I dont have permission to", event.getMember().getId(), vc.getName())).queue(); return; } + + voiceChannelId = vc.getIdLong(); AudioManager manager = event.getGuild().getAudioManager(); manager.openAudioConnection(vc); @@ -156,8 +184,10 @@ public class GuildMusicHandler { manager.setSendingHandler(new EightTrackAudioSendHandler(player)); if (ts.hasTracks()) { + lastPlayed = OffsetDateTime.now(); + AudioTrack track = ts.getNextTrack(); - + MessageEmbed embed = new EmbedBuilder() .setAuthor(event.getMember().getEffectiveName(), null, event.getAuthor().getAvatarUrl()) .setTitle("Now Playing:") From af8e8fa52aaa1dcf68a8c8faa1a2b56e9785438c Mon Sep 17 00:00:00 2001 From: Isaac Parenteau Date: Sun, 6 Oct 2019 20:07:47 -0500 Subject: [PATCH 3/4] Initial Database Migration --- .gitignore | 3 + pom.xml | 2 +- .../config/EightTrackBeanConfiguration.java | 156 ++++++++++++ .../database/config/EightTrackDataSource.java | 162 +++++++++++++ .../database/entities/DiscordGuild.java | 145 +++++++++++ .../database/repos/GuildRepository.java | 52 ++++ .../eighttrack/enums/Configuration.java | 127 ++++++++++ .../DiscordEventHandler.java} | 116 +++++---- .../handlers/GuildMusicHandler.java | 42 +++- .../eighttrack/handlers/Mp3UploadHandler.java | 88 ++++--- .../eighttrack/handlers/Mp3UploadResults.java | 188 ++++++++++++++ .../eighttrack/main/EightTrackLauncher.java | 46 +++- .../eighttrack/services/AESService.java | 74 ++++++ .../services/ConfigurationService.java | 229 ++++++++++++++++++ .../services/DatabaseCleanupService.java | 113 +++++++++ .../services/EightTrackService.java | 69 ++++++ .../services/GuildMusicService.java | 41 ++++ .../migration/mariadb/afterMigrate.sql | 8 +- src/main/resources/eighttrack.properties | 10 + src/main/resources/log4j2.xml | 9 +- 20 files changed, 1567 insertions(+), 113 deletions(-) create mode 100644 src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackBeanConfiguration.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackDataSource.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/database/entities/DiscordGuild.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildRepository.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/enums/Configuration.java rename src/main/java/net/locusworks/discord/eighttrack/{adaptors/MusicListenerAdaptor.java => handlers/DiscordEventHandler.java} (53%) create mode 100644 src/main/java/net/locusworks/discord/eighttrack/services/AESService.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/services/ConfigurationService.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/services/DatabaseCleanupService.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/services/EightTrackService.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/services/GuildMusicService.java create mode 100644 src/main/resources/eighttrack.properties diff --git a/.gitignore b/.gitignore index 0d44024..0955990 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ /nbactions.xml .bin /bin/ +/key.bin +/logs/ +/conf/ diff --git a/pom.xml b/pom.xml index 6e99497..45168e0 100644 --- a/pom.xml +++ b/pom.xml @@ -148,7 +148,7 @@ net.locusworks crypto - 1.0.3-RELEASE + 1.0.5-RELEASE diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackBeanConfiguration.java b/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackBeanConfiguration.java new file mode 100644 index 0000000..9366796 --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackBeanConfiguration.java @@ -0,0 +1,156 @@ +/** + * + * Project: Eight Track, File: EightTrackBeanConfiguration.java + * + * Copyright 2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +package net.locusworks.discord.eighttrack.database.config; + +import java.util.HashSet; +import java.util.Properties; + +import javax.sql.DataSource; + +import org.flywaydb.core.Flyway; +import org.flywaydb.core.api.configuration.FluentConfiguration; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; +import org.springframework.context.annotation.Primary; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.JpaVendorAdapter; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.Database; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration(value="net.locusworks.discord.eighttrack.database.config.EightTrackBeanConfiguration") +@EnableTransactionManagement +@EnableJpaRepositories( + basePackages = {"net.locusworks.discord.eighttrack.database.repos"}, + entityManagerFactoryRef = "eighttrackEntityManagerFactory", + transactionManagerRef = "eighttrackTransactionManager" + ) +public class EightTrackBeanConfiguration { + public static final String PERSISTENCE_UNIT = "eighttrack_pu"; + + public static final HashSet cacheNames = new HashSet<>(); + + private static final String[] PACKAGES_TO_SCAN = { + "net.locusworks.discord.eighttrack.database.entities" + }; + + private static final Properties hibernateProperties; + static { + hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.connection.zeroDateTimeBehavior", "convertToNull"); + hibernateProperties.setProperty("hibernate.dbcp.maxActive", "50"); + hibernateProperties.setProperty("hibernate.dbcp.maxIdle", "10"); + hibernateProperties.setProperty("hibernate.dbcp.maxWait", "5000"); + hibernateProperties.setProperty("hibernate.jdbc.batch_size property", "50"); + hibernateProperties.setProperty("hibernate.connection.charSet", "utf8"); + hibernateProperties.setProperty("hibernate.connection.characterEncoding", "utf8"); + hibernateProperties.setProperty("hibernate.connection.useUnicode", "true"); + hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect"); + } + + @Autowired + private DataSource dataSource; + + @Autowired + private DataSource flywayDataSource; + + /** + * Create the entity manager factory bean used in the database connection + * @return entityManagerFactoryBean + */ + @Primary + @Bean + @DependsOn("flyway") + public LocalContainerEntityManagerFactoryBean eighttrackEntityManagerFactory() { + LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean(); + lef.setDataSource(dataSource); + lef.setJpaVendorAdapter(eighttrackJpaVendorAdapter()); + lef.setPackagesToScan(PACKAGES_TO_SCAN); + lef.setJpaProperties(hibernateProperties); + lef.setPersistenceUnitName(PERSISTENCE_UNIT); + return lef; + } + + /** + * Create the session factory bean + * @return sessionFactoryBean + */ + @Bean + public LocalSessionFactoryBean pseduobotSessionFactory() { + LocalSessionFactoryBean sessionBean = new LocalSessionFactoryBean(); + sessionBean.setDataSource(dataSource); + sessionBean.setPackagesToScan(PACKAGES_TO_SCAN); + sessionBean.setHibernateProperties(hibernateProperties); + return sessionBean; + } + + /** + * Create the JPA Vendor adaptor bean that is used in the entity manager factory + * @return jpaVendorAdaptor + */ + @Primary + @Bean + public JpaVendorAdapter eighttrackJpaVendorAdapter() { + HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter(); + hibernateJpaVendorAdapter.setShowSql(false); + hibernateJpaVendorAdapter.setGenerateDdl(false); + hibernateJpaVendorAdapter.setDatabase(Database.MYSQL); + return hibernateJpaVendorAdapter; + } + + /** + * Create the transaction manager bean + * @return transactionManager + */ + @Primary + @Bean + public PlatformTransactionManager eighttrackTransactionManager() { + JpaTransactionManager manager = new JpaTransactionManager(); + manager.setEntityManagerFactory(eighttrackEntityManagerFactory().getObject()); + return new JpaTransactionManager(); + } + + @Bean(name="flyway", initMethod="migrate") + public Flyway flyway() { + FluentConfiguration fc = Flyway.configure(); + fc.schemas("eighttrack"); + fc.table("_flyway_migration"); + fc.locations("database/migration"); + fc.outOfOrder(false); + fc.dataSource(flywayDataSource); + + return fc.load(); + } + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackDataSource.java b/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackDataSource.java new file mode 100644 index 0000000..db14060 --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackDataSource.java @@ -0,0 +1,162 @@ +/** + * + * Project: Eight Track, File: EightTrackDataSource.java + * + * Copyright 2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +package net.locusworks.discord.eighttrack.database.config; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.TimeZone; +import java.util.stream.Collectors; + +import javax.sql.DataSource; + +import org.apache.commons.dbcp2.ConnectionFactory; +import org.apache.commons.dbcp2.DriverManagerConnectionFactory; +import org.apache.commons.dbcp2.PoolableConnection; +import org.apache.commons.dbcp2.PoolableConnectionFactory; +import org.apache.commons.dbcp2.PoolingDataSource; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.pool2.impl.AbandonedConfig; +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.mariadb.jdbc.MariaDbDataSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +import net.locusworks.discord.eighttrack.services.ConfigurationService; + +@Primary +@Component +public class EightTrackDataSource { + + private static final String DRIVER = "com.mysql.cj.jdbc.Driver"; + + private static final String JNDI_STRING = "jdbc:mysql://%s:%d%s"; + + private static Map mysqlProperties; + static { + mysqlProperties = new LinkedHashMap<>(); + mysqlProperties.put("rewriteBatchedStatements", "true"); + mysqlProperties.put("zeroDateTimeBehavior", "CONVERT_TO_NULL"); + mysqlProperties.put("useSSL", "false"); + mysqlProperties.put("serverTimezone", TimeZone.getDefault().getDisplayName(false, TimeZone.SHORT)); + } + + private Logger logger = LoggerFactory.getLogger(EightTrackDataSource.class); + + @Autowired + private ConfigurationService confService; + + /** + * Create the data source bean + * @return the data source bean + * @throws Exception + */ + @Bean + public DataSource dataSource() throws Exception { + return getDataSource(false); + } + + @Bean + public DataSource flywayDataSource() throws Exception { + logger.debug("Logging in with flyway for migrations"); + + String user = confService.getDatabaseRootUsername(); + String passwd = confService.getDatabaseRootPassword(); + + String url = String.format("jdbc:mariadb://%s:%d?user=%s&password=%s", + confService.getDatabaseHost(), confService.getDatabasePort(), + user, passwd); + + MariaDbDataSource mariadbDS = new MariaDbDataSource(url); + + return mariadbDS; + } + + private DataSource getDataSource(Boolean isFlyway) throws Exception { + logger.debug("Gettind datasource"); + Class.forName(DRIVER).getDeclaredConstructor().newInstance(); + + String user = confService.getDatabaseUsername(); + String passwd = confService.getDatabasePassword(); + + Properties props = new Properties(); + props.setProperty("user", user); + props.setProperty("password", passwd); + + List params = mysqlProperties + .entrySet() + .stream() + .map(prop -> String.format("%s=%s", prop.getKey(), prop.getValue())) + .collect(Collectors.toList()); + + String host = confService.getDatabaseHost(); + int port = confService.getDatabasePort(); + + String url = String.format(JNDI_STRING, host, port, "/eighttrack"); + + url = String.format("%s?%s", url, StringUtils.join(params, "&")); + + logger.debug("Database connection string: %s", url); + + ConnectionFactory cf = new DriverManagerConnectionFactory(url, props); + //Create the poolable connection factory + PoolableConnectionFactory pcf = new PoolableConnectionFactory(cf, null); + pcf.setValidationQuery("SELECT 1"); + pcf.setDefaultAutoCommit(true); + + GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); + poolConfig.setMinIdle(10); + poolConfig.setMaxTotal(100); + + AbandonedConfig abandonConfig = new AbandonedConfig(); + abandonConfig.setRemoveAbandonedTimeout(60); + abandonConfig.setLogAbandoned(false); + abandonConfig.setRemoveAbandonedOnBorrow(true); + abandonConfig.setRemoveAbandonedOnMaintenance(true); + + //Create the pool of connections + GenericObjectPool connectionPool = new GenericObjectPool<>(pcf, poolConfig); + connectionPool.setTestOnBorrow(true); + connectionPool.setTestWhileIdle(true); + connectionPool.setTimeBetweenEvictionRunsMillis(10000); + connectionPool.setMinEvictableIdleTimeMillis(1000); + connectionPool.setAbandonedConfig(abandonConfig); + pcf.setPool(connectionPool); + + //Pooling data source itself + PoolingDataSource dataSource = new PoolingDataSource<>(connectionPool); + return dataSource; + } + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/entities/DiscordGuild.java b/src/main/java/net/locusworks/discord/eighttrack/database/entities/DiscordGuild.java new file mode 100644 index 0000000..1f79f3c --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/database/entities/DiscordGuild.java @@ -0,0 +1,145 @@ +/** + * + * Project: Eight Track, File: DiscordGuild.java + * + * Copyright 2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package net.locusworks.discord.eighttrack.database.entities; + +import java.io.Serializable; +import java.util.Date; +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +/** + * + * @author isaac + */ +@Entity +@Table(name = "discord_guild", catalog = "eighttrack", schema = "") +@NamedQueries({ + @NamedQuery(name = "DiscordGuild.findAll", query = "SELECT d FROM DiscordGuild d")}) +public class DiscordGuild implements Serializable { + + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Basic(optional = false) + @Column(name = "id") + private Long id; + @Basic(optional = false) + @Column(name = "guild_id") + private long guildId; + @Basic(optional = false) + @Column(name = "guild_name") + private String guildName; + @Column(name = "date_joined") + @Temporal(TemporalType.TIMESTAMP) + private Date dateJoined; + + public DiscordGuild() { + } + + public DiscordGuild(Long id) { + this.id = id; + } + + public DiscordGuild(Long id, long guildId, String guildName) { + this.id = id; + this.guildId = guildId; + this.guildName = guildName; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public long getGuildId() { + return guildId; + } + + public void setGuildId(long guildId) { + this.guildId = guildId; + } + + public String getGuildName() { + return guildName; + } + + public void setGuildName(String guildName) { + this.guildName = guildName; + } + + public Date getDateJoined() { + return dateJoined; + } + + public void setDateJoined(Date dateJoined) { + this.dateJoined = dateJoined; + } + + @Override + public int hashCode() { + int hash = 0; + hash += (id != null ? id.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object object) { + // TODO: Warning - this method won't work in the case the id fields are not set + if (!(object instanceof DiscordGuild)) { + return false; + } + DiscordGuild other = (DiscordGuild) object; + if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { + return false; + } + return true; + } + + @Override + public String toString() { + return "net.locusworks.discord.pseudobot.database.entities.DiscordGuild[ id=" + id + " ]"; + } + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildRepository.java b/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildRepository.java new file mode 100644 index 0000000..95e09d8 --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildRepository.java @@ -0,0 +1,52 @@ +/** + * + * Project: Eight Track, File: GuildRepository.java + * + * Copyright 2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +package net.locusworks.discord.eighttrack.database.repos; + +import java.util.List; +import java.util.Set; + +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.transaction.annotation.Transactional; + +import net.locusworks.discord.eighttrack.database.entities.DiscordGuild; + +public interface GuildRepository extends CrudRepository { + + DiscordGuild findByGuildId(Long serverId); + + @Query("SELECT g FROM DiscordGuild g WHERE g.guildId NOT IN ?1") + List findGuildsNoLongerJoined(Set serverIds); + + @Query("DELETE FROM DiscordGuild g WHERE g.guildId NOT IN ?1") + @Modifying + @Transactional + void deleteGuildsNoLongerJoined(Set guildIds); + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/enums/Configuration.java b/src/main/java/net/locusworks/discord/eighttrack/enums/Configuration.java new file mode 100644 index 0000000..de7ec76 --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/enums/Configuration.java @@ -0,0 +1,127 @@ +/** + * + * Project: Eight Track, File: Configuration.java + * + * Copyright 2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +package net.locusworks.discord.eighttrack.enums; + +public enum Configuration { + DB_ROOT_USER("dbAdmin"), + DB_ROOT_PASSWORD("dbAdminPassword"), + DB_USER("dbUser"), + DB_PASSWORD("dbUserPassword"), + DB_HOST("dbHost"), + DB_PORT("dbPort"), + LOG_LEVEL("logLevel"), + MUSIC_DIR("musicDir"), + DISCORD_TOKEN("discordToken"); + + private String value; + + private Configuration(String value) { + this.value = value; + } + + /** + * Get the current value of the enumeration + * @return value + */ + public String getValue() { + return this.value; + } + + @Override + public String toString() { + return this.value; + } + + /** + * Checks to see if the configuration is of a certain value + * @param confTypes types to check against + * @return true if the current configuration is of a certain enumeration, false otherwise + */ + public boolean is(Configuration... confTypes) { + for (Configuration confType : confTypes) { + if (this == confType) { + return true; + } + } + return false; + } + + /** + * Checks to see if the configuration is not of a certain value + * @param confTypes Types to check against + * @return true if the current configuration is not of a certain enuermation, false otherwise + */ + public boolean isNot(Configuration... confTypes) { + return !is(confTypes); + } + + /** + * Finds a specific enumeration + * @param value Value to find + * @return the found enumeration or null if nothing is found + */ + public static Configuration findEnum(String value) { + for (Configuration conf: values()) { + if (conf.getValue().equalsIgnoreCase(value)) { + return conf; + } + } + return null; + } + + /** + * Checks to see if a specific value is in a set of configuration types + * @param value Value to look for + * @param confTypes types to compare against + * @return true if the string value is in a certain set of configuration enumerations, false otherwise + */ + public static boolean in(String value, Configuration... confTypes) { + Configuration ft = findEnum(value); + if (ft == null) { + return false; + } + + for (Configuration confType : confTypes) { + if (ft == confType) { + return true; + } + } + + return false; + } + + /** + * Checks to see if a specific value is not in a set of configuration types + * @param value Value to look for + * @param confTypes types to compare against + * @return true if the string value is not in a certain set of configuration enumerations, false otherwise + */ + public static boolean notIn(String value, Configuration... confTypes) { + return !in(value, confTypes); + } +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/adaptors/MusicListenerAdaptor.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/DiscordEventHandler.java similarity index 53% rename from src/main/java/net/locusworks/discord/eighttrack/adaptors/MusicListenerAdaptor.java rename to src/main/java/net/locusworks/discord/eighttrack/handlers/DiscordEventHandler.java index 1a7113e..c6844e4 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/adaptors/MusicListenerAdaptor.java +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/DiscordEventHandler.java @@ -1,6 +1,6 @@ /** * - * Project: Eight Track, File: MusicListenerAdaptor.java + * Project: Eight Track, File: DiscordEventHandler.java * * Copyright 2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by @@ -25,66 +25,71 @@ * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, * ENHANCEMENTS, OR MODIFICATIONS. */ -package net.locusworks.discord.eighttrack.adaptors; +package net.locusworks.discord.eighttrack.handlers; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; -import java.time.Duration; -import java.time.OffsetDateTime; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.Date; +import javax.annotation.PostConstruct; -import net.dv8tion.jda.api.JDA; -import net.dv8tion.jda.api.entities.Guild; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import net.dv8tion.jda.api.events.guild.GuildJoinEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.locusworks.discord.eighttrack.handlers.GuildMusicHandler; +import net.locusworks.discord.eighttrack.database.entities.DiscordGuild; +import net.locusworks.discord.eighttrack.database.repos.GuildRepository; +import net.locusworks.discord.eighttrack.services.ConfigurationService; +import net.locusworks.discord.eighttrack.services.GuildMusicService; import net.locusworks.logger.ApplicationLogger; import net.locusworks.logger.ApplicationLoggerFactory; -public class MusicListenerAdaptor extends ListenerAdapter { +@Service +public class DiscordEventHandler extends ListenerAdapter { private Path musicDir; - private ApplicationLogger logger; - - private Map playerMap; - private JDA client; - public MusicListenerAdaptor(Path musicDir, JDA client) throws IOException { - this.logger = ApplicationLoggerFactory.getLogger(MusicListenerAdaptor.class); - this.playerMap = new ConcurrentHashMap<>(); - this.musicDir = musicDir; - this.client = client; - - ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); - executor.scheduleWithFixedDelay(()->checkPlayers(), 1, 1, TimeUnit.MINUTES); - + private ApplicationLogger logger = ApplicationLoggerFactory.getLogger(DiscordEventHandler.class); + + @Autowired + private ConfigurationService confService; + + @Autowired + private GuildRepository guildRepo; + + @Autowired + private GuildMusicService musicService; + + @Autowired + private Mp3UploadHandler uploadHandler; + + @PostConstruct + private void init() throws IOException { + this.musicDir = confService.getMusicDirectory(); + if (!Files.exists(this.musicDir.toAbsolutePath())) { + Files.createDirectories(this.musicDir.toAbsolutePath()); + } } - private void checkPlayers() { - logger.debug("Checking players to see if anyone is listening"); - OffsetDateTime now = OffsetDateTime.now(); - for(Iterator> iterator = playerMap.entrySet().iterator(); iterator.hasNext();) { - Entry entry = iterator.next(); - GuildMusicHandler gmh = entry.getValue(); - long guildId = entry.getKey(); - - OffsetDateTime lastPlayed = gmh.getLastPlayed(); - Duration duration = Duration.between(lastPlayed, now); - if (duration.getSeconds() > 300) { - Guild guild = client.getGuildById(guildId); - if (guild == null) { - iterator.remove(); - continue; - } - guild.getAudioManager().closeAudioConnection(); - iterator.remove(); - } + @Override + public void onGuildJoin(GuildJoinEvent event) { + try { + long guildId = event.getGuild().getIdLong(); + DiscordGuild discordGuild = guildRepo.findByGuildId(guildId); + if (discordGuild != null) return; + + logger.debug("Joining Server: " + event.getGuild().getName()); + + discordGuild = new DiscordGuild(); + discordGuild.setGuildId(guildId); + discordGuild.setGuildName(event.getGuild().getName()); + discordGuild.setDateJoined(new Date()); + + guildRepo.save(discordGuild); + } catch (Exception ex) { + logger.error("Unable to persist server information to database: " + ex.getMessage(), ex); } } @@ -100,13 +105,21 @@ public class MusicListenerAdaptor extends ListenerAdapter { private void onGuildMessageReceivedHelper(GuildMessageReceivedEvent event) throws IOException { - if (!playerMap.containsKey(event.getGuild().getIdLong())) { - playerMap.put(event.getGuild().getIdLong(), new GuildMusicHandler(musicDir)); + if (!musicService.containsKey(event.getGuild().getIdLong())) { + musicService.put(event.getGuild().getIdLong(), new GuildMusicHandler(musicDir, uploadHandler)); } - GuildMusicHandler gmh = playerMap.get(event.getGuild().getIdLong()); - gmh.accept((id) -> playerMap.remove(id)); + GuildMusicHandler gmh = musicService.get(event.getGuild().getIdLong()); + gmh.accept((id) -> musicService.remove(id)); String command = event.getMessage().getContentRaw().trim().toLowerCase(); + + switch(command) { + case "-upload": + gmh.upload(event); + return; + } + + /* switch (command) { case "-play": gmh.isPlaying(true); @@ -132,5 +145,6 @@ public class MusicListenerAdaptor extends ListenerAdapter { default: return; } + */ } } diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java index 177e862..315bbde 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java @@ -27,6 +27,7 @@ */ package net.locusworks.discord.eighttrack.handlers; +import java.awt.Color; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -45,6 +46,7 @@ import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.ChannelType; import net.dv8tion.jda.api.entities.GuildChannel; +import net.dv8tion.jda.api.entities.Message.Attachment; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.VoiceChannel; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; @@ -66,13 +68,14 @@ public class GuildMusicHandler { private OffsetDateTime lastPlayed; private Consumer callback; + private Mp3UploadHandler uploadHandler; - public GuildMusicHandler(Path musicDir) throws IOException { + public GuildMusicHandler(Path musicDir, Mp3UploadHandler uploadHandler) throws IOException { this.logger = ApplicationLoggerFactory.getLogger(GuildMusicHandler.class); this.playing = new AtomicBoolean(false); this.musicDir = musicDir; this.lastPlayed = OffsetDateTime.now(); - + this.uploadHandler = uploadHandler; this.apm = new DefaultAudioPlayerManager(); AudioSourceManagers.registerLocalSource(apm); @@ -80,7 +83,6 @@ public class GuildMusicHandler { this.ts = new TrackScheduler(); player.addListener(ts); - indexFiles(); } public OffsetDateTime getLastPlayed() { @@ -200,4 +202,38 @@ public class GuildMusicHandler { ts.trackLoaded(track); } } + + public void upload(GuildMessageReceivedEvent event) { + if (!event.getMessage().getMember().hasPermission(Permission.ADMINISTRATOR, Permission.MANAGE_SERVER)) { + event.getChannel().sendMessage(String.format("Sorry <@%s> i can't do that. *psst: you have to have manage server, or administrator role*", event.getMember().getIdLong())).queue(); + return; + } + + for(Attachment attachment : event.getMessage().getAttachments()) { + attachment.retrieveInputStream().thenAccept((in) -> { + try { + Mp3UploadResults res = uploadHandler.parse(in); + + MessageEmbed embed = new EmbedBuilder() + .setColor(Color.GREEN) + .setTitle("Upload Results") + .setDescription(res.toString()) + .setTimestamp(OffsetDateTime.now()) + .setFooter(event.getGuild().getSelfMember().getEffectiveName(), event.getGuild().getSelfMember().getUser().getAvatarUrl()) + .build(); + + event.getChannel().sendMessage(embed).queue(); + } catch (Exception ex) { + logger.error("Unable to get file information: %s", ex.getMessage()); + logger.error(ex); + } finally { + event.getMessage().delete().queue(); + } + + }).exceptionally((err) ->{ + return null; + }); + } + + } } diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadHandler.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadHandler.java index 294ae90..be6ed7e 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadHandler.java +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadHandler.java @@ -1,3 +1,30 @@ +/** + * + * Project: Eight Track, File: Mp3UploadHandler.java + * + * Copyright 2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ package net.locusworks.discord.eighttrack.handlers; import java.io.IOException; @@ -9,52 +36,41 @@ import java.nio.file.Paths; import org.apache.tika.exception.TikaException; import org.apache.tika.metadata.Metadata; import org.apache.tika.parser.ParseContext; -import org.apache.tika.parser.mp3.LyricsHandler; import org.apache.tika.parser.mp3.Mp3Parser; import org.apache.tika.sax.BodyContentHandler; +import org.springframework.stereotype.Component; import org.xml.sax.SAXException; +@Component public class Mp3UploadHandler { - - private Path file; - - public Mp3UploadHandler(Path file) { - this.file = file; - } - - public void parse() throws IOException, SAXException, TikaException { - - InputStream is = Files.newInputStream(file); - - BodyContentHandler handler = new BodyContentHandler(); - Metadata metadata = new Metadata(); - ParseContext context = new ParseContext(); - - Mp3Parser parser = new Mp3Parser(); - - parser.parse(is, handler, metadata, context); - - LyricsHandler lyrics = new LyricsHandler(is, handler); - - while(lyrics.hasLyrics()) { - System.out.println(lyrics.toString()); - } - - System.out.println("Contents of the document:" + handler.toString()); - System.out.println("Metadata of the document:"); - String[] metadataNames = metadata.names(); - for(String name : metadataNames) { - System.out.println(name + ": " + metadata.get(name)); + public Mp3UploadResults parse(Path file) throws IOException { + InputStream is = Files.newInputStream(file); + return parse(is); + } + + public Mp3UploadResults parse(InputStream is) throws IOException { + try { + BodyContentHandler handler = new BodyContentHandler(); + Metadata metadata = new Metadata(); + ParseContext context = new ParseContext(); + + Mp3Parser parser = new Mp3Parser(); + + parser.parse(is, handler, metadata, context); + + return new Mp3UploadResults(metadata); + } catch (Exception ex) { + throw new IOException(ex); } } - + public static void main(String args[]) throws IOException, SAXException, TikaException { - String file = "S:\\Music\\Alan Walker\\01 Diamond Heart.mp3"; + String file = "E:\\Music2\\Alan Walker\\Itinerary_ Dallas.pdf"; Path path = Paths.get(file); - - Mp3UploadHandler fuh = new Mp3UploadHandler(path); - fuh.parse(); + + Mp3UploadHandler fuh = new Mp3UploadHandler(); + fuh.parse(path); } } diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadResults.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadResults.java index 138351e..cb016be 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadResults.java +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadResults.java @@ -1,15 +1,203 @@ +/** + * + * Project: Eight Track, File: Mp3UploadResults.java + * + * Copyright 2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ package net.locusworks.discord.eighttrack.handlers; import org.apache.tika.metadata.Metadata; public class Mp3UploadResults { + private enum MetaDataField { + GENRE("xmpDM:genre"), + COMPOSER("xmpDM:composer"), + ALBUM("xmpDM:album"), + TRACK_NUMBER("xmpDM:trackNumber"), + DISC_NUMBER("xmpDM:discNumber"), + ARTIST("xmpDM:artist"), + TITLE("title"), + RELEASE_DATE("xmpDM:releaseDate"), + DURATION("xmpDM:duration"); + + private String value; + + private MetaDataField(String value) { + this.value = value; + } + + public String getValue() { + return this.value; + } + } + + private String genre; + private String composure; + private String album; + private String trackNumber; + private String discNumber; + private String artist; + private String title; + private String releaseDate; + private Long duration; + + public Mp3UploadResults( Metadata metadata) { parseResults(metadata); } private void parseResults(Metadata metadata) { + genre = metadata.get(MetaDataField.GENRE.getValue()); + composure = metadata.get(MetaDataField.COMPOSER.getValue()); + album = metadata.get(MetaDataField.ALBUM.getValue()); + trackNumber = metadata.get(MetaDataField.TRACK_NUMBER.getValue()); + discNumber = metadata.get(MetaDataField.DISC_NUMBER.getValue()); + artist = metadata.get(MetaDataField.ARTIST.getValue()); + title = metadata.get(MetaDataField.TITLE.getValue()); + releaseDate = metadata.get(MetaDataField.RELEASE_DATE.getValue()); + String durationStr = metadata.get(MetaDataField.DURATION.getValue()).trim(); + if (durationStr != null) { + duration = Double.valueOf(metadata.get(MetaDataField.DURATION.getValue())).longValue(); + } + } + + /** + * @return the genre + */ + public final String getGenre() { + return genre; + } + + /** + * @return the composure + */ + public final String getComposure() { + return composure; + } + + /** + * @return the album + */ + public final String getAlbum() { + return album; + } + + /** + * @return the trackNumber + */ + public final String getTrackNumber() { + return trackNumber; + } + + /** + * @return the discNumber + */ + public final String getDiscNumber() { + return discNumber; + } + + /** + * @return the artist + */ + public final String getArtist() { + return artist; + } + + /** + * @return the title + */ + public final String getTitle() { + return title; + } + + /** + * @return the releaseDate + */ + public final String getReleaseDate() { + return releaseDate; + } + + /** + * @return the duration + */ + public final Long getDuration() { + return duration; + } + + public boolean validFile() { + return getTitle() != null && !getTitle().isEmpty(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("```"); + if (getTitle() != null) + sb.append(String.format("%-10s: %s%n", "Title", getTitle())); + + if (getArtist() != null) + sb.append(String.format("%-10s: %s%n", "Artist", getArtist())); + + if (getAlbum() != null) + sb.append(String.format("%-10s: %s%n", "Album", getAlbum())); + + if (getTrackNumber() != null) + sb.append(String.format("%-10s: %s%n", "Track", getTrackNumber())); + + if (getDiscNumber() != null) + sb.append(String.format("%-10s: %s%n", "Disc", getDiscNumber())); + + if (getReleaseDate() != null) + sb.append(String.format("%-10s: %s%n", "Year", getReleaseDate())); + + if (getGenre() != null) + sb.append(String.format("%-10s: %s%n", "Genre", getGenre())); + + if (duration != null) + sb.append(String.format("%-10s: %s%n", "Duration", dateFormat(getDuration()))); + + sb.append("```"); + return sb.toString(); + } + + private String dateFormat(long timeInMilliSeconds) { + long seconds = timeInMilliSeconds / 1000; + long minutes = seconds / 60; + long hours = minutes / 60; + long days = hours / 24; + + long sec = seconds % 60; + long min = minutes % 60; + long hr = hours % 24; + + String time = "" + sec; + if (min > 0) time = min + ":" + time; + if (hr > 0) time = hr + ":" + time; + if (days > 0) time = days + ":" + time; + + return time; } } diff --git a/src/main/java/net/locusworks/discord/eighttrack/main/EightTrackLauncher.java b/src/main/java/net/locusworks/discord/eighttrack/main/EightTrackLauncher.java index 1f2f2d7..7c09013 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/main/EightTrackLauncher.java +++ b/src/main/java/net/locusworks/discord/eighttrack/main/EightTrackLauncher.java @@ -1,6 +1,6 @@ /** * - * Project: Eight Track, File: Entry.java + * Project: Eight Track, File: EightTrackLauncher.java * * Copyright 2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by @@ -28,33 +28,53 @@ package net.locusworks.discord.eighttrack.main; import java.io.IOException; -import java.nio.file.Paths; import javax.security.auth.login.LoginException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.scheduling.annotation.EnableScheduling; -import net.dv8tion.jda.api.AccountType; -import net.dv8tion.jda.api.JDA; -import net.dv8tion.jda.api.JDABuilder; -import net.locusworks.discord.eighttrack.adaptors.MusicListenerAdaptor; +import net.locusworks.discord.eighttrack.services.ConfigurationService; +import net.locusworks.discord.eighttrack.services.EightTrackService; import net.locusworks.logger.ApplicationLogger; import net.locusworks.logger.ApplicationLoggerFactory; +import net.locusworks.logger.ApplicationLoggerInitializer; +import net.locusworks.logger.LogLevel; -@SpringBootApplication(scanBasePackages = {"net.locusworks.discord.pseudobot"}) +@SpringBootApplication(scanBasePackages = {"net.locusworks.discord.eighttrack"}) @EnableAutoConfiguration @EnableScheduling -public class EightTrackLauncher { +public class EightTrackLauncher implements ApplicationRunner { + + @Autowired + private ConfigurationService confService; + + @Autowired + private EightTrackService service; public static void main(String[] args) throws LoginException, IOException { - if (args.length < 1) throw new RuntimeException("no token provided"); + new SpringApplicationBuilder(EightTrackLauncher.class).headless(true).run(args); + } + @Override + public void run(ApplicationArguments args) throws Exception { + ApplicationLoggerFactory.init(new ApplicationLoggerInitializer() { + + @Override + public LogLevel initialize() { + return LogLevel.getEnum(confService.getLogLevel()); + } + }); + ApplicationLogger logger = ApplicationLoggerFactory.getLogger(EightTrackLauncher.class); logger.info("Starting Eight-Track"); - - JDA client = new JDABuilder(AccountType.BOT).setToken(args[0]).build(); - - client.addEventListener(new MusicListenerAdaptor(Paths.get(args[1]))); + + service.begin(); + + } } diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/AESService.java b/src/main/java/net/locusworks/discord/eighttrack/services/AESService.java new file mode 100644 index 0000000..1351190 --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/services/AESService.java @@ -0,0 +1,74 @@ +/** + * + * Project: Eight Track, File: AESService.java + * + * Copyright 2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +package net.locusworks.discord.eighttrack.services; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import javax.annotation.PostConstruct; + +import org.apache.commons.io.IOUtils; +import org.springframework.stereotype.Service; + +import net.locusworks.crypto.AES; + +@Service +public class AESService { + private AES aes; + + @PostConstruct + private void init() throws IOException { + Path keyFile = Paths.get("key.bin"); + if (!Files.exists(keyFile)) { + throw new IOException("Unable to find key.bin in local directory"); + } + + byte[] key = IOUtils.toByteArray(Files.newInputStream(keyFile)); + + this.aes = AES.createInstance(key); + } + + public String encrypt(String plainText) { + return aes.encrypt(plainText); + } + + public String decrypt(String encryptedText) { + return aes.decrypt(encryptedText); + } + + public static void main(String[] args) throws IOException { + AESService service = new AESService(); + service.init(); + + System.out.println(service.encrypt("zeGAPgbH9HFbqmjRjmwzUDKv")); + + } + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/ConfigurationService.java b/src/main/java/net/locusworks/discord/eighttrack/services/ConfigurationService.java new file mode 100644 index 0000000..c2614f1 --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/services/ConfigurationService.java @@ -0,0 +1,229 @@ +/** + * + * Project: Eight Track, File: ConfigurationService.java + * + * Copyright 2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +package net.locusworks.discord.eighttrack.services; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Map; +import java.util.Properties; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import net.locusworks.crypto.configuration.PropertiesManager; +import net.locusworks.discord.eighttrack.enums.Configuration; +import net.locusworks.logger.ApplicationLogger; +import net.locusworks.logger.ApplicationLoggerFactory; + +@Service +public class ConfigurationService { + private Properties configuration; + private Properties defaults = null; + private Path eightTrackConf = null; + private long lastModified = 0; + + private static final String PROPERTIES_FILE = "eighttrack.properties"; + + private static ApplicationLogger logger = ApplicationLoggerFactory.getLogger(ConfigurationService.class); + + @Autowired + private AESService aesService; + + /** + * Initialize the configuration service + * This happens during server start up + * @throws IOException If the file cannot be read + * @throws Exception any other exception thrown + */ + @PostConstruct + private void init() throws IOException, Exception { + + // load defaults when the webapp loads + try { + defaults = PropertiesManager.loadConfiguration(this.getClass(), PROPERTIES_FILE); + } catch (IOException ex) { + logger.error(String.format("Failed to load default %s: %s", PROPERTIES_FILE, ex.getMessage())); + throw ex; + } + + // create portalConf File object + eightTrackConf = Paths.get("conf").resolve(PROPERTIES_FILE); + + if (!Files.exists(eightTrackConf.getParent())) { + Files.createDirectories(eightTrackConf.getParent()); + } + + // initial config load + loadConf(); + } + + /** + * Load the configuration file + * @throws IOException + */ + private void loadConf() throws IOException { + + // load the active config file + // ignore read error, we can continue with an empty configuration map + // and all default items will be added below and the file created + logger.info("Loading config file: " + eightTrackConf); + try { + configuration = PropertiesManager.loadConfiguration(eightTrackConf); + } catch (Exception e) { + logger.info("Config file: " + eightTrackConf + " will be created from template"); + configuration = new Properties(); + } + + Map results = PropertiesManager.addConfiguration(configuration, defaults); + boolean changed = !results.isEmpty(); + if (!results.isEmpty()) { + logger.info(results, new StringBuilder("Added new configuration items:%n")); + } + + results = PropertiesManager.removeConfiguration(configuration, defaults); + changed |= !results.isEmpty(); + if (!results.isEmpty()) { + logger.info(results, new StringBuilder("Removed unused configuration items:%n")); + } + + if (changed) { + PropertiesManager.saveConfiguration(configuration, eightTrackConf, "Patch Repository properties file"); + } + + lastModified = Files.getLastModifiedTime(eightTrackConf).toMillis(); + } + + public String getLogLevel() { + return configuration.getProperty(Configuration.LOG_LEVEL.getValue()); + } + + /** + * Save the configuration values to file + * @param confs Configuration property values to save + * @throws Exception general exception + */ + public void saveToConf(Properties confs) throws Exception { + PropertiesManager.saveConfiguration(confs, eightTrackConf, "Patch Repository properties file"); + logger.info("Saved config file: " + eightTrackConf + ", " + confs.size() + " entries"); + loadConf(); + } + + /** + * Get the database root user name. + * It first checks the catalina.properties file for the root user + * then checks the patchrepo.properties file + * @return root database username + */ + public String getDatabaseRootUsername() { + return configuration.getProperty(Configuration.DB_ROOT_USER.getValue()); + } + + /** + * Get the database root user password + * It first checks the catalina.properties file for the password + * then checks the patchrepo.properties file. + * The password must be encrypted in both locations + * @return root database password + */ + public String getDatabaseRootPassword() { + String dbPasswd = configuration.getProperty(Configuration.DB_ROOT_PASSWORD.getValue()); + try { + return aesService.decrypt(dbPasswd); + } catch (Exception ex) { + logger.error("Unable to get db root password " + ex.getMessage()); + return null; + } + } + + + /** + * Get the standard database user name + * @return portal database username + */ + public String getDatabaseUsername() { + return configuration.getProperty(Configuration.DB_USER.getValue()); + } + + /** + * Get the standard database password. + * The password is encrypted in the properties file + * @return patchrepo database password + */ + public String getDatabasePassword() { + String dbPasswd = configuration.getProperty(Configuration.DB_PASSWORD.getValue()); + try { + return aesService.decrypt(dbPasswd); + } catch (Exception ex) { + logger.error("Unable to get db password " + ex.getMessage()); + return null; + } + } + + /** + * Get the database host url + * @return database host url + */ + public String getDatabaseHost() { + return configuration.getProperty(Configuration.DB_HOST.getValue()); + } + + /** + * Get the database host port + * @return the database port + */ + public Integer getDatabasePort() { + return Integer.parseInt(configuration.getProperty(Configuration.DB_PORT.getValue())); + } + + /** + * Get the discord token + * @return discord token + */ + public String getDiscordToken() { + String token = configuration.getProperty(Configuration.DISCORD_TOKEN.getValue(), ""); + return token; + } + + public Path getMusicDirectory() { + String dir = configuration.getProperty(Configuration.MUSIC_DIR.getValue(), ""); + return Paths.get(dir); + } + + /** + * Get the last time the configuration file was modified + * @return last modified + */ + public long getLastModified() { + return lastModified; + } + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/DatabaseCleanupService.java b/src/main/java/net/locusworks/discord/eighttrack/services/DatabaseCleanupService.java new file mode 100644 index 0000000..8ef52c3 --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/services/DatabaseCleanupService.java @@ -0,0 +1,113 @@ +/** + * + * Project: Eight Track, File: DatabaseCleanupService.java + * + * Copyright 2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +package net.locusworks.discord.eighttrack.services; + +import java.time.Duration; +import java.time.OffsetDateTime; +import java.util.Iterator; +import java.util.Set; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.Guild; +import net.locusworks.discord.eighttrack.database.repos.GuildRepository; +import net.locusworks.discord.eighttrack.handlers.GuildMusicHandler; + +@Service +public class DatabaseCleanupService { + + private static final long SECOND = 1000; + private static final long MINUTE = 60 * SECOND; + private static final long HOUR = 60 * MINUTE; + private static final long DAY = 24 * HOUR; + + private Logger logger = LoggerFactory.getLogger(DatabaseCleanupService.class); + + @Autowired + private GuildRepository guildRepo; + + @Autowired + private GuildMusicService musicService; + + private JDA client; + + public void setClient(JDA client) { + this.client = client; + } + + @Scheduled(fixedRate = 5 * MINUTE) + private void checkPlayers() { + if (client == null) { + logger.warn("Discord client is null. Unable to do cleanup"); + return; + } + + logger.debug("Checking players to see if anyone is listening"); + OffsetDateTime now = OffsetDateTime.now(); + for(Iterator> iterator = musicService.entrySet().iterator(); iterator.hasNext();) { + Entry entry = iterator.next(); + GuildMusicHandler gmh = entry.getValue(); + long guildId = entry.getKey(); + + OffsetDateTime lastPlayed = gmh.getLastPlayed(); + Duration duration = Duration.between(lastPlayed, now); + if (duration.getSeconds() > 300) { + Guild guild = client.getGuildById(guildId); + if (guild == null) { + iterator.remove(); + continue; + } + guild.getAudioManager().closeAudioConnection(); + iterator.remove(); + } + } + } + + @Scheduled(fixedRate = DAY) + private void cleanDatabase() { + if (client == null) { + logger.warn("Discord client is null. Unable to do cleanup"); + return; + } + + Set currentGuildsIds = client.getSelfUser().getMutualGuilds().stream().map(guild -> guild.getIdLong()).collect(Collectors.toSet()); + + try { + guildRepo.deleteGuildsNoLongerJoined(currentGuildsIds); + } catch (Exception ex) { + logger.error("Unable to clean up servers: " + ex.getMessage()); + } + } +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/EightTrackService.java b/src/main/java/net/locusworks/discord/eighttrack/services/EightTrackService.java new file mode 100644 index 0000000..2ccf575 --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/services/EightTrackService.java @@ -0,0 +1,69 @@ +/** + * + * Project: Eight Track, File: EightTrackService.java + * + * Copyright 2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +package net.locusworks.discord.eighttrack.services; + +import javax.security.auth.login.LoginException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import net.dv8tion.jda.api.AccountType; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; +import net.locusworks.discord.eighttrack.handlers.DiscordEventHandler; +import net.locusworks.logger.ApplicationLogger; +import net.locusworks.logger.ApplicationLoggerFactory; + +@Service +public class EightTrackService { + + private ApplicationLogger logger = ApplicationLoggerFactory.getLogger(EightTrackService.class); + + private JDA client; + + @Autowired + private ConfigurationService confService; + + @Autowired + private DiscordEventHandler eventListener; + + @Autowired + private DatabaseCleanupService dcs; + + public void begin() throws LoginException { + String token = confService.getDiscordToken(); + logger.debug("Logging in with token %s", token); + + client = new JDABuilder(AccountType.BOT).setToken(token).build(); + client.addEventListener(eventListener); + + dcs.setClient(client); + } + + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/GuildMusicService.java b/src/main/java/net/locusworks/discord/eighttrack/services/GuildMusicService.java new file mode 100644 index 0000000..fede33a --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/services/GuildMusicService.java @@ -0,0 +1,41 @@ +/** + * + * Project: Eight Track, File: GuildMusicService.java + * + * Copyright 2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +package net.locusworks.discord.eighttrack.services; + +import java.util.concurrent.ConcurrentHashMap; + +import org.springframework.stereotype.Service; + +import net.locusworks.discord.eighttrack.handlers.GuildMusicHandler; + +@Service +public class GuildMusicService extends ConcurrentHashMap { + + private static final long serialVersionUID = -120204711554552975L; + +} diff --git a/src/main/resources/database/migration/mariadb/afterMigrate.sql b/src/main/resources/database/migration/mariadb/afterMigrate.sql index 629d102..57a53a8 100644 --- a/src/main/resources/database/migration/mariadb/afterMigrate.sql +++ b/src/main/resources/database/migration/mariadb/afterMigrate.sql @@ -13,11 +13,11 @@ BEGIN DECLARE foo BIGINT DEFAULT 0; SELECT COUNT(*) INTO foo FROM mysql.user WHERE User = 'eighttrackAdmin' and Host = 'localhost'; IF foo = 0 THEN - CREATE USER 'eighttrackAdmin'@'localhost' IDENTIFIED BY 'eighttrackAdmin2017!'; + CREATE USER 'eighttrackAdmin'@'localhost' IDENTIFIED BY 'zeGAPgbH9HFbqmjRjmwzUDKv'; END IF; SELECT COUNT(*) INTO foo FROM mysql.user WHERE User = 'eighttrackAdmin' and Host = '%'; IF foo = 0 THEN - CREATE USER 'eighttrackAdmin'@'%' IDENTIFIED BY 'eighttrackAdmin2017!'; + CREATE USER 'eighttrackAdmin'@'%' IDENTIFIED BY 'zeGAPgbH9HFbqmjRjmwzUDKv'; END IF; END ;$$ @@ -29,6 +29,6 @@ DROP PROCEDURE set_optimizer_switch_on; CALL create_user(); DROP PROCEDURE create_user; -GRANT SELECT,INSERT,UPDATE,DELETE ON pseudobot.* TO 'eighttrackAdmin'@'localhost'; -GRANT SELECT,INSERT,UPDATE,DELETE ON pseudobot.* TO 'eighttrackAdmin'@'%'; +GRANT SELECT,INSERT,UPDATE,DELETE ON eighttrack.* TO 'eighttrackAdmin'@'localhost'; +GRANT SELECT,INSERT,UPDATE,DELETE ON eighttrack.* TO 'eighttrackAdmin'@'%'; FLUSH PRIVILEGES; \ No newline at end of file diff --git a/src/main/resources/eighttrack.properties b/src/main/resources/eighttrack.properties new file mode 100644 index 0000000..9d405df --- /dev/null +++ b/src/main/resources/eighttrack.properties @@ -0,0 +1,10 @@ +dbAdmin=root +dbAdminPassword=gSkjsvZbQTQtogOrPYqorCuuzp4WUpGFVtPYtMVj47U= +dbUser=eighttrackAdmin +dbUserPassword=RaamWDMgA2p09R3kAiKHqauu6mmKU2HLQ4nAfEGMNOs= +dbHost=devops.locusworks.net +dbPort=3306 +logLevel=INFO +musicDir=E:/Music +discordToken=NjI5MTQ0OTk1ODA2MzE0NTA5.XZVlRQ.7hiB0u4Zp5pxPrPfvdOdyr4TCh4 + diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 2ae8612..756ed17 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -3,7 +3,6 @@ - ${sys:LOG_LEVEL:-INFO} %d{dd-MMM-yyyy HH:mm:ss.SSS} [%-5p] [%c{1}] %m%n @@ -11,8 +10,8 @@ + fileName="logs/eighttrack.log" + filePattern="logs/eighttrack-%d{yyyy-MM-dd}.log.gz"> @@ -22,8 +21,8 @@ - - + + From 50b6cea57ba23aaa56a6940976a8c437b09505c6 Mon Sep 17 00:00:00 2001 From: Isaac Parenteau Date: Sun, 6 Oct 2019 22:02:16 -0500 Subject: [PATCH 4/4] Refactored to use database #5 Switched to use maria database to store song information #7 Added spring and hibernate support #8 Added song upload functionality --- licenses/LICENSE.template | 2 +- pom.xml | 12 +- .../config/EightTrackBeanConfiguration.java | 2 +- .../database/config/EightTrackDataSource.java | 2 +- .../database/entities/DiscordGuild.java | 27 +- .../database/entities/GuildPlaylist.java | 171 ++++++++++++ .../database/entities/GuildPlaylistSong.java | 141 ++++++++++ .../database/entities/GuildSong.java | 154 +++++++++++ .../eighttrack/database/entities/Song.java | 253 ++++++++++++++++++ .../database/repos/GuildRepository.java | 2 +- .../database/repos/GuildSongRepository.java | 51 ++++ .../database/repos/SongRepository.java | 39 +++ .../eighttrack/enums/Configuration.java | 2 +- .../handlers/DiscordEventHandler.java | 8 +- .../handlers/EightTrackAudioSendHandler.java | 2 +- .../handlers/GuildMusicHandler.java | 89 +++++- .../eighttrack/handlers/Mp3UploadHandler.java | 20 +- .../eighttrack/handlers/Mp3UploadResults.java | 17 +- .../eighttrack/main/EightTrackLauncher.java | 2 +- .../eighttrack/scheduler/TrackScheduler.java | 2 +- .../eighttrack/services/AESService.java | 2 +- .../services/ConfigurationService.java | 2 +- .../services/DatabaseCleanupService.java | 2 +- .../services/EightTrackService.java | 2 +- .../services/GuildMusicService.java | 2 +- .../services/GuildSongRepoService.java | 70 +++++ src/main/resources/META-INF/persistence.xml | 17 ++ .../Tables/V01_000_000__initial_tables.sql | 55 ++++ 28 files changed, 1113 insertions(+), 37 deletions(-) create mode 100644 src/main/java/net/locusworks/discord/eighttrack/database/entities/GuildPlaylist.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/database/entities/GuildPlaylistSong.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/database/entities/GuildSong.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/database/entities/Song.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildSongRepository.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/database/repos/SongRepository.java create mode 100644 src/main/java/net/locusworks/discord/eighttrack/services/GuildSongRepoService.java create mode 100644 src/main/resources/META-INF/persistence.xml diff --git a/licenses/LICENSE.template b/licenses/LICENSE.template index 55f2e67..7fe38d6 100644 --- a/licenses/LICENSE.template +++ b/licenses/LICENSE.template @@ -1,7 +1,7 @@ Project: ${project.name}, File: ${file.name} -Copyright ${license.git.copyrightLastYear} Locusworks LLC. +Copyright 2019-${license.git.copyrightLastYear} Locusworks LLC. All rights reserved. Federal copyright law prohibits unauthorized reproduction by any means and imposes fines up to $25,000 for violation. No part of this material may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/pom.xml b/pom.xml index 45168e0..4dd03d9 100644 --- a/pom.xml +++ b/pom.xml @@ -332,7 +332,17 @@ activation 1.1.1 - + + org.eclipse.persistence + eclipselink + 2.5.2 + + + org.eclipse.persistence + org.eclipse.persistence.jpa.modelgen.processor + 2.5.2 + provided + diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackBeanConfiguration.java b/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackBeanConfiguration.java index 9366796..cca6994 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackBeanConfiguration.java +++ b/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackBeanConfiguration.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: EightTrackBeanConfiguration.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackDataSource.java b/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackDataSource.java index db14060..a596f3d 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackDataSource.java +++ b/src/main/java/net/locusworks/discord/eighttrack/database/config/EightTrackDataSource.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: EightTrackDataSource.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/entities/DiscordGuild.java b/src/main/java/net/locusworks/discord/eighttrack/database/entities/DiscordGuild.java index 1f79f3c..114be6e 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/database/entities/DiscordGuild.java +++ b/src/main/java/net/locusworks/discord/eighttrack/database/entities/DiscordGuild.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: DiscordGuild.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, @@ -34,7 +34,9 @@ package net.locusworks.discord.eighttrack.database.entities; import java.io.Serializable; import java.util.Date; +import java.util.List; import javax.persistence.Basic; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -42,6 +44,7 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; @@ -71,6 +74,10 @@ public class DiscordGuild implements Serializable { @Column(name = "date_joined") @Temporal(TemporalType.TIMESTAMP) private Date dateJoined; + @OneToMany(cascade = CascadeType.ALL, mappedBy = "guild") + private List guildSongList; + @OneToMany(cascade = CascadeType.ALL, mappedBy = "guild") + private List guildPlaylistList; public DiscordGuild() { } @@ -117,6 +124,22 @@ public class DiscordGuild implements Serializable { this.dateJoined = dateJoined; } + public List getGuildSongList() { + return guildSongList; + } + + public void setGuildSongList(List guildSongList) { + this.guildSongList = guildSongList; + } + + public List getGuildPlaylistList() { + return guildPlaylistList; + } + + public void setGuildPlaylistList(List guildPlaylistList) { + this.guildPlaylistList = guildPlaylistList; + } + @Override public int hashCode() { int hash = 0; @@ -139,7 +162,7 @@ public class DiscordGuild implements Serializable { @Override public String toString() { - return "net.locusworks.discord.pseudobot.database.entities.DiscordGuild[ id=" + id + " ]"; + return "net.locusworks.discord.eighttrack.database.entities.DiscordGuild[ id=" + id + " ]"; } } diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/entities/GuildPlaylist.java b/src/main/java/net/locusworks/discord/eighttrack/database/entities/GuildPlaylist.java new file mode 100644 index 0000000..a29ea7f --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/database/entities/GuildPlaylist.java @@ -0,0 +1,171 @@ +/** + * + * Project: Eight Track, File: GuildPlaylist.java + * + * Copyright 2019-2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package net.locusworks.discord.eighttrack.database.entities; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import javax.persistence.Basic; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +/** + * + * @author isaac + */ +@Entity +@Table(name = "guild_playlist", catalog = "eighttrack", schema = "") +@NamedQueries({ + @NamedQuery(name = "GuildPlaylist.findAll", query = "SELECT g FROM GuildPlaylist g")}) +public class GuildPlaylist implements Serializable { + + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Basic(optional = false) + @Column(name = "id") + private Long id; + @Basic(optional = false) + @Column(name = "userId") + private long userId; + @Basic(optional = false) + @Column(name = "playlist") + private String playlist; + @Column(name = "date_added") + @Temporal(TemporalType.TIMESTAMP) + private Date dateAdded; + @OneToMany(cascade = CascadeType.ALL, mappedBy = "guildPlaylist") + private List guildPlaylistSongList; + @JoinColumn(name = "guild", referencedColumnName = "id") + @ManyToOne(optional = false) + private DiscordGuild guild; + + public GuildPlaylist() { + } + + public GuildPlaylist(Long id) { + this.id = id; + } + + public GuildPlaylist(Long id, long userId, String playlist) { + this.id = id; + this.userId = userId; + this.playlist = playlist; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public long getUserId() { + return userId; + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public String getPlaylist() { + return playlist; + } + + public void setPlaylist(String playlist) { + this.playlist = playlist; + } + + public Date getDateAdded() { + return dateAdded; + } + + public void setDateAdded(Date dateAdded) { + this.dateAdded = dateAdded; + } + + public List getGuildPlaylistSongList() { + return guildPlaylistSongList; + } + + public void setGuildPlaylistSongList(List guildPlaylistSongList) { + this.guildPlaylistSongList = guildPlaylistSongList; + } + + public DiscordGuild getGuild() { + return guild; + } + + public void setGuild(DiscordGuild guild) { + this.guild = guild; + } + + @Override + public int hashCode() { + int hash = 0; + hash += (id != null ? id.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object object) { + // TODO: Warning - this method won't work in the case the id fields are not set + if (!(object instanceof GuildPlaylist)) { + return false; + } + GuildPlaylist other = (GuildPlaylist) object; + if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { + return false; + } + return true; + } + + @Override + public String toString() { + return "net.locusworks.discord.eighttrack.database.entities.GuildPlaylist[ id=" + id + " ]"; + } + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/entities/GuildPlaylistSong.java b/src/main/java/net/locusworks/discord/eighttrack/database/entities/GuildPlaylistSong.java new file mode 100644 index 0000000..d837d25 --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/database/entities/GuildPlaylistSong.java @@ -0,0 +1,141 @@ +/** + * + * Project: Eight Track, File: GuildPlaylistSong.java + * + * Copyright 2019-2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package net.locusworks.discord.eighttrack.database.entities; + +import java.io.Serializable; +import java.util.Date; +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +/** + * + * @author isaac + */ +@Entity +@Table(name = "guild_playlist_song", catalog = "eighttrack", schema = "") +@NamedQueries({ + @NamedQuery(name = "GuildPlaylistSong.findAll", query = "SELECT g FROM GuildPlaylistSong g")}) +public class GuildPlaylistSong implements Serializable { + + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Basic(optional = false) + @Column(name = "id") + private Long id; + @Column(name = "date_added") + @Temporal(TemporalType.TIMESTAMP) + private Date dateAdded; + @JoinColumn(name = "guild_playlist", referencedColumnName = "id") + @ManyToOne(optional = false) + private GuildPlaylist guildPlaylist; + @JoinColumn(name = "guild_song", referencedColumnName = "id") + @ManyToOne(optional = false) + private GuildSong guildSong; + + public GuildPlaylistSong() { + } + + public GuildPlaylistSong(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Date getDateAdded() { + return dateAdded; + } + + public void setDateAdded(Date dateAdded) { + this.dateAdded = dateAdded; + } + + public GuildPlaylist getGuildPlaylist() { + return guildPlaylist; + } + + public void setGuildPlaylist(GuildPlaylist guildPlaylist) { + this.guildPlaylist = guildPlaylist; + } + + public GuildSong getGuildSong() { + return guildSong; + } + + public void setGuildSong(GuildSong guildSong) { + this.guildSong = guildSong; + } + + @Override + public int hashCode() { + int hash = 0; + hash += (id != null ? id.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object object) { + // TODO: Warning - this method won't work in the case the id fields are not set + if (!(object instanceof GuildPlaylistSong)) { + return false; + } + GuildPlaylistSong other = (GuildPlaylistSong) object; + if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { + return false; + } + return true; + } + + @Override + public String toString() { + return "net.locusworks.discord.eighttrack.database.entities.GuildPlaylistSong[ id=" + id + " ]"; + } + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/entities/GuildSong.java b/src/main/java/net/locusworks/discord/eighttrack/database/entities/GuildSong.java new file mode 100644 index 0000000..91cf503 --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/database/entities/GuildSong.java @@ -0,0 +1,154 @@ +/** + * + * Project: Eight Track, File: GuildSong.java + * + * Copyright 2019-2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package net.locusworks.discord.eighttrack.database.entities; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import javax.persistence.Basic; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +/** + * + * @author isaac + */ +@Entity +@Table(name = "guild_song", catalog = "eighttrack", schema = "") +@NamedQueries({ + @NamedQuery(name = "GuildSong.findAll", query = "SELECT g FROM GuildSong g")}) +public class GuildSong implements Serializable { + + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Basic(optional = false) + @Column(name = "id") + private Long id; + @Column(name = "date_added") + @Temporal(TemporalType.TIMESTAMP) + private Date dateAdded; + @JoinColumn(name = "guild", referencedColumnName = "id") + @ManyToOne(optional = false) + private DiscordGuild guild; + @JoinColumn(name = "song", referencedColumnName = "id") + @ManyToOne(optional = false) + private Song song; + @OneToMany(cascade = CascadeType.ALL, mappedBy = "guildSong") + private List guildPlaylistSongList; + + public GuildSong() { + } + + public GuildSong(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Date getDateAdded() { + return dateAdded; + } + + public void setDateAdded(Date dateAdded) { + this.dateAdded = dateAdded; + } + + public DiscordGuild getGuild() { + return guild; + } + + public void setGuild(DiscordGuild guild) { + this.guild = guild; + } + + public Song getSong() { + return song; + } + + public void setSong(Song song) { + this.song = song; + } + + public List getGuildPlaylistSongList() { + return guildPlaylistSongList; + } + + public void setGuildPlaylistSongList(List guildPlaylistSongList) { + this.guildPlaylistSongList = guildPlaylistSongList; + } + + @Override + public int hashCode() { + int hash = 0; + hash += (id != null ? id.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object object) { + // TODO: Warning - this method won't work in the case the id fields are not set + if (!(object instanceof GuildSong)) { + return false; + } + GuildSong other = (GuildSong) object; + if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { + return false; + } + return true; + } + + @Override + public String toString() { + return "net.locusworks.discord.eighttrack.database.entities.GuildSong[ id=" + id + " ]"; + } + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/entities/Song.java b/src/main/java/net/locusworks/discord/eighttrack/database/entities/Song.java new file mode 100644 index 0000000..c31ff5e --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/database/entities/Song.java @@ -0,0 +1,253 @@ +/** + * + * Project: Eight Track, File: Song.java + * + * Copyright 2019-2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package net.locusworks.discord.eighttrack.database.entities; + +import java.io.Serializable; +import java.math.BigInteger; +import java.util.Date; +import java.util.List; +import javax.persistence.Basic; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +/** + * + * @author isaac + */ +@Entity +@Table(name = "song", catalog = "eighttrack", schema = "") +@NamedQueries({ + @NamedQuery(name = "Song.findAll", query = "SELECT s FROM Song s")}) +public class Song implements Serializable { + + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Basic(optional = false) + @Column(name = "id") + private Long id; + @Basic(optional = false) + @Column(name = "uuid") + private String uuid; + @Basic(optional = false) + @Column(name = "title") + private String title; + @Column(name = "artist") + private String artist; + @Column(name = "album") + private String album; + @Column(name = "genre") + private String genre; + @Column(name = "track_number") + private String trackNumber; + @Column(name = "disc_number") + private String discNumber; + @Column(name = "release_year") + private String releaseYear; + @Column(name = "duration") + private BigInteger duration; + @Basic(optional = false) + @Column(name = "file_path") + private String filePath; + @Basic(optional = false) + @Column(name = "file_hash") + private String fileHash; + @Column(name = "date_added") + @Temporal(TemporalType.TIMESTAMP) + private Date dateAdded; + @OneToMany(cascade = CascadeType.ALL, mappedBy = "song") + private List guildSongList; + + public Song() { + } + + public Song(Long id) { + this.id = id; + } + + public Song(Long id, String uuid, String title, String filePath, String fileHash) { + this.id = id; + this.uuid = uuid; + this.title = title; + this.filePath = filePath; + this.fileHash = fileHash; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getArtist() { + return artist; + } + + public void setArtist(String artist) { + this.artist = artist; + } + + public String getAlbum() { + return album; + } + + public void setAlbum(String album) { + this.album = album; + } + + public String getGenre() { + return genre; + } + + public void setGenre(String genre) { + this.genre = genre; + } + + public String getTrackNumber() { + return trackNumber; + } + + public void setTrackNumber(String trackNumber) { + this.trackNumber = trackNumber; + } + + public String getDiscNumber() { + return discNumber; + } + + public void setDiscNumber(String discNumber) { + this.discNumber = discNumber; + } + + public String getReleaseYear() { + return releaseYear; + } + + public void setReleaseYear(String releaseYear) { + this.releaseYear = releaseYear; + } + + public BigInteger getDuration() { + return duration; + } + + public void setDuration(BigInteger duration) { + this.duration = duration; + } + + public String getFilePath() { + return filePath; + } + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public String getFileHash() { + return fileHash; + } + + public void setFileHash(String fileHash) { + this.fileHash = fileHash; + } + + public Date getDateAdded() { + return dateAdded; + } + + public void setDateAdded(Date dateAdded) { + this.dateAdded = dateAdded; + } + + public List getGuildSongList() { + return guildSongList; + } + + public void setGuildSongList(List guildSongList) { + this.guildSongList = guildSongList; + } + + @Override + public int hashCode() { + int hash = 0; + hash += (id != null ? id.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object object) { + // TODO: Warning - this method won't work in the case the id fields are not set + if (!(object instanceof Song)) { + return false; + } + Song other = (Song) object; + if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { + return false; + } + return true; + } + + @Override + public String toString() { + return "net.locusworks.discord.eighttrack.database.entities.Song[ id=" + id + " ]"; + } + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildRepository.java b/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildRepository.java index 95e09d8..4650ee3 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildRepository.java +++ b/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildRepository.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: GuildRepository.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildSongRepository.java b/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildSongRepository.java new file mode 100644 index 0000000..a069a4d --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildSongRepository.java @@ -0,0 +1,51 @@ +/** + * + * Project: Eight Track, File: GuildSongRepository.java + * + * Copyright 2019-2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +package net.locusworks.discord.eighttrack.database.repos; + +import java.util.List; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; + +import net.locusworks.discord.eighttrack.database.entities.DiscordGuild; +import net.locusworks.discord.eighttrack.database.entities.GuildSong; +import net.locusworks.discord.eighttrack.database.entities.Song; + +public interface GuildSongRepository extends CrudRepository { + + GuildSong findByGuildAndSong(DiscordGuild guild, Song song); + + @Query("SELECT gs FROM GuildSong gs WHERE gs.guild.guildId = ?1 AND gs.song.fileHash = ?2") + GuildSong findByGuildAndSongHash(Long guildId, String songHash); + + List findByGuild(DiscordGuild guild); + + @Query("SELECT gs FROM GuildSong gs WHERE gs.guild.guildId = ?1") + List findByGuild(Long guildId); + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/repos/SongRepository.java b/src/main/java/net/locusworks/discord/eighttrack/database/repos/SongRepository.java new file mode 100644 index 0000000..e0ea5bd --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/database/repos/SongRepository.java @@ -0,0 +1,39 @@ +/** + * + * Project: Eight Track, File: SongRepository.java + * + * Copyright 2019-2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +package net.locusworks.discord.eighttrack.database.repos; + +import org.springframework.data.repository.CrudRepository; +import net.locusworks.discord.eighttrack.database.entities.Song; + +public interface SongRepository extends CrudRepository { + + Song findByUuid(String uuid); + + Song findByFileHash(String fileHash); + +} diff --git a/src/main/java/net/locusworks/discord/eighttrack/enums/Configuration.java b/src/main/java/net/locusworks/discord/eighttrack/enums/Configuration.java index de7ec76..9927b0e 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/enums/Configuration.java +++ b/src/main/java/net/locusworks/discord/eighttrack/enums/Configuration.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: Configuration.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/DiscordEventHandler.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/DiscordEventHandler.java index c6844e4..de041bb 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/handlers/DiscordEventHandler.java +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/DiscordEventHandler.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: DiscordEventHandler.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, @@ -43,6 +43,7 @@ import net.locusworks.discord.eighttrack.database.entities.DiscordGuild; import net.locusworks.discord.eighttrack.database.repos.GuildRepository; import net.locusworks.discord.eighttrack.services.ConfigurationService; import net.locusworks.discord.eighttrack.services.GuildMusicService; +import net.locusworks.discord.eighttrack.services.GuildSongRepoService; import net.locusworks.logger.ApplicationLogger; import net.locusworks.logger.ApplicationLoggerFactory; @@ -64,6 +65,9 @@ public class DiscordEventHandler extends ListenerAdapter { @Autowired private Mp3UploadHandler uploadHandler; + + @Autowired + private GuildSongRepoService guildSongRepoService; @PostConstruct private void init() throws IOException { @@ -106,7 +110,7 @@ public class DiscordEventHandler extends ListenerAdapter { private void onGuildMessageReceivedHelper(GuildMessageReceivedEvent event) throws IOException { if (!musicService.containsKey(event.getGuild().getIdLong())) { - musicService.put(event.getGuild().getIdLong(), new GuildMusicHandler(musicDir, uploadHandler)); + musicService.put(event.getGuild().getIdLong(), new GuildMusicHandler(musicDir, uploadHandler, guildSongRepoService)); } GuildMusicHandler gmh = musicService.get(event.getGuild().getIdLong()); gmh.accept((id) -> musicService.remove(id)); diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/EightTrackAudioSendHandler.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/EightTrackAudioSendHandler.java index e05df0b..335e61a 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/handlers/EightTrackAudioSendHandler.java +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/EightTrackAudioSendHandler.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: EightTrackAudioSendHandler.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java index 315bbde..4162671 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: GuildMusicHandler.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, @@ -29,10 +29,13 @@ package net.locusworks.discord.eighttrack.handlers; import java.awt.Color; import java.io.IOException; +import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; import java.time.OffsetDateTime; +import java.util.Date; import java.util.List; +import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -51,7 +54,12 @@ import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.VoiceChannel; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.api.managers.AudioManager; +import net.locusworks.crypto.utils.HashUtils; +import net.locusworks.discord.eighttrack.database.entities.DiscordGuild; +import net.locusworks.discord.eighttrack.database.entities.GuildSong; +import net.locusworks.discord.eighttrack.database.entities.Song; import net.locusworks.discord.eighttrack.scheduler.TrackScheduler; +import net.locusworks.discord.eighttrack.services.GuildSongRepoService; import net.locusworks.logger.ApplicationLogger; import net.locusworks.logger.ApplicationLoggerFactory; @@ -69,13 +77,15 @@ public class GuildMusicHandler { private Consumer callback; private Mp3UploadHandler uploadHandler; + private GuildSongRepoService guildSongRepoService; - public GuildMusicHandler(Path musicDir, Mp3UploadHandler uploadHandler) throws IOException { + public GuildMusicHandler(Path musicDir, Mp3UploadHandler uploadHandler, GuildSongRepoService guildSongRepoService) throws IOException { this.logger = ApplicationLoggerFactory.getLogger(GuildMusicHandler.class); this.playing = new AtomicBoolean(false); this.musicDir = musicDir; this.lastPlayed = OffsetDateTime.now(); this.uploadHandler = uploadHandler; + this.guildSongRepoService = guildSongRepoService; this.apm = new DefaultAudioPlayerManager(); AudioSourceManagers.registerLocalSource(apm); @@ -211,16 +221,13 @@ public class GuildMusicHandler { for(Attachment attachment : event.getMessage().getAttachments()) { attachment.retrieveInputStream().thenAccept((in) -> { + Mp3UploadResults res = null; try { - Mp3UploadResults res = uploadHandler.parse(in); - - MessageEmbed embed = new EmbedBuilder() - .setColor(Color.GREEN) - .setTitle("Upload Results") - .setDescription(res.toString()) - .setTimestamp(OffsetDateTime.now()) - .setFooter(event.getGuild().getSelfMember().getEffectiveName(), event.getGuild().getSelfMember().getUser().getAvatarUrl()) - .build(); + MessageEmbed embed = null; + res = uploadHandler.parse(in); + if (res.validFile()) { + embed =persistSong(res, event, attachment.getFileName()); + } event.getChannel().sendMessage(embed).queue(); } catch (Exception ex) { @@ -228,12 +235,72 @@ public class GuildMusicHandler { logger.error(ex); } finally { event.getMessage().delete().queue(); + if (res != null) res.clear(); } }).exceptionally((err) ->{ return null; }); } + } + + private MessageEmbed persistSong(Mp3UploadResults result, GuildMessageReceivedEvent event, String fileName) throws Exception { + + DiscordGuild guild = guildSongRepoService.getGuildRepo().findByGuildId(event.getGuild().getIdLong()); + if(guild == null) { + throw new IOException("Unable to find guild in database. Please contact administrator"); + } + + Path output = musicDir; + if (result.getArtist() != null) { + output = output.resolve(result.getArtist()); + if (result.getAlbum() != null) { + output = output.resolve(result.getAlbum()); + } + } + output = output.resolve(fileName); + + if (!Files.exists(output.toAbsolutePath().getParent())) { + Files.createDirectories(output.toAbsolutePath().getParent()); + } + + Files.write(output, result.getData()); + + Song song = new Song(); + song.setAlbum(result.getAlbum()); + song.setArtist(result.getArtist()); + song.setDateAdded(new Date()); + song.setDiscNumber(result.getDiscNumber()); + if (result.getDuration() != null) + song.setDuration(BigInteger.valueOf(result.getDuration())); + song.setFileHash(HashUtils.hash("SHA-1", result.getData())); + song.setFilePath(output.toAbsolutePath().toString()); + song.setGenre(result.getGenre()); + song.setReleaseYear(result.getReleaseDate()); + song.setTitle(result.getTitle()); + song.setTrackNumber(result.getTrackNumber()); + song.setUuid(UUID.nameUUIDFromBytes(result.getData()).toString()); + + guildSongRepoService.getSongRepo().save(song); + + GuildSong gs = new GuildSong(); + gs.setDateAdded(new Date()); + gs.setGuild(guild); + gs.setSong(song); + + guildSongRepoService.getGuildSongRepo().save(gs); + + String out = String.format("```%s%n%-10s: %s```", result, "UUID", song.getUuid()); + + MessageEmbed embed = new EmbedBuilder() + .setColor(Color.GREEN) + .setTitle("Upload Results for " + fileName) + .setDescription(out) + .setTimestamp(OffsetDateTime.now()) + .setFooter(event.getGuild().getSelfMember().getEffectiveName(), event.getGuild().getSelfMember().getUser().getAvatarUrl()) + .build(); + + return embed; } } diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadHandler.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadHandler.java index be6ed7e..b511448 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadHandler.java +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadHandler.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: Mp3UploadHandler.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, @@ -27,6 +27,8 @@ */ package net.locusworks.discord.eighttrack.handlers; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; @@ -50,16 +52,26 @@ public class Mp3UploadHandler { } public Mp3UploadResults parse(InputStream is) throws IOException { - try { + byte[] data; + try(InputStream in = is; ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + int read = 0; + byte[] buffer = new byte[1024 * 1024]; + while((read = in.read(buffer)) > 0) { + baos.write(buffer, 0, read); + } + data = baos.toByteArray(); + } + + try (InputStream in = new ByteArrayInputStream(data)) { BodyContentHandler handler = new BodyContentHandler(); Metadata metadata = new Metadata(); ParseContext context = new ParseContext(); Mp3Parser parser = new Mp3Parser(); - parser.parse(is, handler, metadata, context); + parser.parse(in, handler, metadata, context); - return new Mp3UploadResults(metadata); + return new Mp3UploadResults(metadata, data); } catch (Exception ex) { throw new IOException(ex); } diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadResults.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadResults.java index cb016be..174e33a 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadResults.java +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/Mp3UploadResults.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: Mp3UploadResults.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, @@ -63,9 +63,11 @@ public class Mp3UploadResults { private String releaseDate; private Long duration; + private byte[] rawData; - public Mp3UploadResults( Metadata metadata) { + public Mp3UploadResults( Metadata metadata, byte[] data) { parseResults(metadata); + this.rawData = data; } private void parseResults(Metadata metadata) { @@ -83,6 +85,10 @@ public class Mp3UploadResults { duration = Double.valueOf(metadata.get(MetaDataField.DURATION.getValue())).longValue(); } } + + public final byte[] getData() { + return this.rawData; + } /** * @return the genre @@ -153,7 +159,7 @@ public class Mp3UploadResults { @Override public String toString() { - StringBuilder sb = new StringBuilder("```"); + StringBuilder sb = new StringBuilder(); if (getTitle() != null) sb.append(String.format("%-10s: %s%n", "Title", getTitle())); @@ -178,10 +184,13 @@ public class Mp3UploadResults { if (duration != null) sb.append(String.format("%-10s: %s%n", "Duration", dateFormat(getDuration()))); - sb.append("```"); return sb.toString(); } + public void clear() { + rawData = new byte[0]; + } + private String dateFormat(long timeInMilliSeconds) { long seconds = timeInMilliSeconds / 1000; long minutes = seconds / 60; diff --git a/src/main/java/net/locusworks/discord/eighttrack/main/EightTrackLauncher.java b/src/main/java/net/locusworks/discord/eighttrack/main/EightTrackLauncher.java index 7c09013..5298c09 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/main/EightTrackLauncher.java +++ b/src/main/java/net/locusworks/discord/eighttrack/main/EightTrackLauncher.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: EightTrackLauncher.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/src/main/java/net/locusworks/discord/eighttrack/scheduler/TrackScheduler.java b/src/main/java/net/locusworks/discord/eighttrack/scheduler/TrackScheduler.java index 715a047..f7bb4a1 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/scheduler/TrackScheduler.java +++ b/src/main/java/net/locusworks/discord/eighttrack/scheduler/TrackScheduler.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: TrackScheduler.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/AESService.java b/src/main/java/net/locusworks/discord/eighttrack/services/AESService.java index 1351190..b3f6e68 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/services/AESService.java +++ b/src/main/java/net/locusworks/discord/eighttrack/services/AESService.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: AESService.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/ConfigurationService.java b/src/main/java/net/locusworks/discord/eighttrack/services/ConfigurationService.java index c2614f1..b349739 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/services/ConfigurationService.java +++ b/src/main/java/net/locusworks/discord/eighttrack/services/ConfigurationService.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: ConfigurationService.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/DatabaseCleanupService.java b/src/main/java/net/locusworks/discord/eighttrack/services/DatabaseCleanupService.java index 8ef52c3..c0fd67f 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/services/DatabaseCleanupService.java +++ b/src/main/java/net/locusworks/discord/eighttrack/services/DatabaseCleanupService.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: DatabaseCleanupService.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/EightTrackService.java b/src/main/java/net/locusworks/discord/eighttrack/services/EightTrackService.java index 2ccf575..1b2ee63 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/services/EightTrackService.java +++ b/src/main/java/net/locusworks/discord/eighttrack/services/EightTrackService.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: EightTrackService.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/GuildMusicService.java b/src/main/java/net/locusworks/discord/eighttrack/services/GuildMusicService.java index fede33a..4db286c 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/services/GuildMusicService.java +++ b/src/main/java/net/locusworks/discord/eighttrack/services/GuildMusicService.java @@ -2,7 +2,7 @@ * * Project: Eight Track, File: GuildMusicService.java * - * Copyright 2019 Locusworks LLC. + * Copyright 2019-2019 Locusworks LLC. * All rights reserved. Federal copyright law prohibits unauthorized reproduction by * any means and imposes fines up to $25,000 for violation. No part of this material * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/GuildSongRepoService.java b/src/main/java/net/locusworks/discord/eighttrack/services/GuildSongRepoService.java new file mode 100644 index 0000000..33ee8cc --- /dev/null +++ b/src/main/java/net/locusworks/discord/eighttrack/services/GuildSongRepoService.java @@ -0,0 +1,70 @@ +/** + * + * Project: Eight Track, File: GuildSongRepoService.java + * + * Copyright 2019-2019 Locusworks LLC. + * All rights reserved. Federal copyright law prohibits unauthorized reproduction by + * any means and imposes fines up to $25,000 for violation. No part of this material + * may be reproduced, transmitted, transcribed, stored in a retrieval system, copied, + * modified, duplicated, adapted or translated into another program language in any + * form or by any means, electronic, mechanical, photocopying, recording, or + * otherwise, without the prior written permission from Locusworks. Locusworks + * affirms that Eight-Track(R) software and data is subject to United States + * Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive + * Forney TX 75126, (802) 488-0438, for commercial licensing opportunities. + * + * IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY + * LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF + * THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND + * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS + * IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + */ +package net.locusworks.discord.eighttrack.services; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import net.locusworks.discord.eighttrack.database.repos.GuildRepository; +import net.locusworks.discord.eighttrack.database.repos.GuildSongRepository; +import net.locusworks.discord.eighttrack.database.repos.SongRepository; + +@Service +public class GuildSongRepoService { + + @Autowired + private GuildRepository guildRepo; + + @Autowired + private GuildSongRepository guildSongRepo; + + @Autowired + private SongRepository songRepo; + + /** + * @return the guildRepo + */ + public final GuildRepository getGuildRepo() { + return guildRepo; + } + + /** + * @return the guildSongRepo + */ + public final GuildSongRepository getGuildSongRepo() { + return guildSongRepo; + } + + /** + * @return the songRepo + */ + public final SongRepository getSongRepo() { + return songRepo; + } + +} diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000..eb8ffd7 --- /dev/null +++ b/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,17 @@ + + + + org.eclipse.persistence.jpa.PersistenceProvider + net.locusworks.discord.eighttrack.database.entities.GuildSong + net.locusworks.discord.eighttrack.database.entities.GuildPlaylist + net.locusworks.discord.eighttrack.database.entities.DiscordGuild + net.locusworks.discord.eighttrack.database.entities.Song + net.locusworks.discord.eighttrack.database.entities.GuildPlaylistSong + + + + + + + + diff --git a/src/main/resources/database/migration/mariadb/Tables/V01_000_000__initial_tables.sql b/src/main/resources/database/migration/mariadb/Tables/V01_000_000__initial_tables.sql index 6aa1706..947cff1 100644 --- a/src/main/resources/database/migration/mariadb/Tables/V01_000_000__initial_tables.sql +++ b/src/main/resources/database/migration/mariadb/Tables/V01_000_000__initial_tables.sql @@ -6,3 +6,58 @@ CREATE TABLE eighttrack.discord_guild ( PRIMARY KEY (id), UNIQUE KEY guild_UN (guild_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Information about discord guild'; + +CREATE TABLE eighttrack.song ( + id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Primary Key', + uuid varchar(100) NOT NULL COMMENT 'Unique Identifier', + title varchar(500) NOT NULL COMMENT 'title of song', + artist varchar(500) DEFAULT NULL COMMENT 'songs artist', + album varchar(500) DEFAULT NULL COMMENT 'songs album', + genre varchar(500) DEFAULT NULL COMMENT 'songs genre', + track_number varchar(100) DEFAULT NULL COMMENT 'track number', + disc_number varchar(100) DEFAULT NULL COMMENT 'disc number', + release_year varchar(100) DEFAULT NULL COMMENT 'release year', + duration bigint(20) DEFAULT NULL COMMENT 'songs duration', + file_path varchar(5000) NOT NULL COMMENT 'file location on local file system', + file_hash varchar(40) NOT NULL COMMENT 'sha1 hash of file', + date_added timestamp NULL DEFAULT NULL, + PRIMARY KEY (id), + UNIQUE KEY song_uuid_UN (uuid), + UNIQUE KEY song_file_hash_UN (file_hash) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE eighttrack.guild_song ( + id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'primary key', + guild bigint(20) NOT NULL COMMENT 'guild the song belongs to', + song bigint(20) NOT NULL COMMENT 'the song', + date_added timestamp NULL DEFAULT NULL COMMENT 'date added', + PRIMARY KEY (id), + UNIQUE KEY guild_song_UN (guild,song), + KEY guild_song_FK_1 (song), + CONSTRAINT guild_song_FK FOREIGN KEY (guild) REFERENCES eighttrack.discord_guild (id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT guild_song_FK_1 FOREIGN KEY (song) REFERENCES eighttrack.song (id) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE eighttrack.guild_playlist ( + id bigint(20) NOT NULL AUTO_INCREMENT, + guild bigint(20) NOT NULL, + userId bigint(20) NOT NULL, + playlist varchar(500) NOT NULL, + date_added timestamp NULL DEFAULT NULL, + PRIMARY KEY (id), + UNIQUE KEY guild_playlist_UN (guild,userId,playlist), + CONSTRAINT guild_playlist_FK FOREIGN KEY (guild) REFERENCES eighttrack.discord_guild (id) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + + +CREATE TABLE eighttrack.guild_playlist_song ( + id bigint(20) NOT NULL AUTO_INCREMENT, + guild_playlist bigint(20) NOT NULL, + guild_song bigint(20) NOT NULL, + date_added timestamp NULL DEFAULT NULL, + PRIMARY KEY (id), + UNIQUE KEY guild_playlist_song_UN (guild_playlist,guild_song), + KEY guild_playlist_song_FK_1 (guild_song), + CONSTRAINT guild_playlist_song_FK FOREIGN KEY (guild_playlist) REFERENCES eighttrack.guild_playlist (id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT guild_playlist_song_FK_1 FOREIGN KEY (guild_song) REFERENCES eighttrack.guild_song (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file