Initial Database Migration
This commit is contained in:
		@@ -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<String> 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();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -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<String, String> 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<String> 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<PoolableConnection> 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<PoolableConnection> 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<PoolableConnection> dataSource = new PoolingDataSource<>(connectionPool);
 | 
			
		||||
    return dataSource;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -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 + " ]";
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
@@ -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, Long> {
 | 
			
		||||
  
 | 
			
		||||
  DiscordGuild findByGuildId(Long serverId);
 | 
			
		||||
  
 | 
			
		||||
  @Query("SELECT g FROM DiscordGuild g WHERE g.guildId NOT IN ?1")
 | 
			
		||||
  List<DiscordGuild> findGuildsNoLongerJoined(Set<Long> serverIds);
 | 
			
		||||
  
 | 
			
		||||
  @Query("DELETE FROM DiscordGuild g WHERE g.guildId NOT IN ?1")
 | 
			
		||||
  @Modifying
 | 
			
		||||
  @Transactional
 | 
			
		||||
  void deleteGuildsNoLongerJoined(Set<Long> guildIds);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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<Long, GuildMusicHandler> 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<Entry<Long, GuildMusicHandler>> iterator = playerMap.entrySet().iterator(); iterator.hasNext();) {
 | 
			
		||||
      Entry<Long, GuildMusicHandler> 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;
 | 
			
		||||
    }
 | 
			
		||||
    */
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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<Long> 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;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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"));
 | 
			
		||||
    
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -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<String, String> 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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -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<Entry<Long, GuildMusicHandler>> iterator = musicService.entrySet().iterator(); iterator.hasNext();) {
 | 
			
		||||
      Entry<Long, GuildMusicHandler> 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<Long> 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());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -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<Long, GuildMusicHandler> {
 | 
			
		||||
 | 
			
		||||
  private static final long serialVersionUID = -120204711554552975L;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user