diff --git a/.gitignore b/.gitignore index b5c16bd..f5e1637 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,10 @@ src/main/ignore_commit outputDir +#Resources config +resources/config.properties +config.properties + .idea/**/vcs.xml # User-specific stuff diff --git a/CHANGELOG.md b/CHANGELOG.md index a5cc324..88d4c3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.0.2-alpha1 (2020.08.02) + + * Added external config option for the auth credentials + * Minor command name fixes + ## 0.0.1-alpha1 (2020.07.24) * Initial commit \ No newline at end of file diff --git a/README.md b/README.md index e88e4e1..40393c0 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ The information about parameters is available in the app when the action is spec #### Recommendations * The fetching period (*DELTA_PERIOD*) specified should have less than ~1000 clips to avoid missing clips (the global fetching period can have any date range). * Fetching can crawl the same clips multiple times. To clean the list `-distinct` can be used. -* CLIENT_ID, CLIENT_SECRET, AUTH_TOKEN can be specified in *ClipsManager* before compiling. It may not be safe, but can be used in some cases to avoid entering credentials every time. +* *clientId*, *clientSecret*, *authToken* can be specified in *config.properties*. There are 2 ways to do it: 1st way - before compiling in the *resources* folder; 2nd way - put *config.properties* in the directory with an executable file (it applies above the embedded one). It may not be safe, but can be used in some cases to avoid entering credentials every time. * Log level can be specified for most classes for the debugging to show more/less info. ## Modules diff --git a/TwitchClipsManager.iml b/TwitchClipsManager.iml index f1cd230..bebfb51 100644 --- a/TwitchClipsManager.iml +++ b/TwitchClipsManager.iml @@ -4,6 +4,7 @@ + diff --git a/config.properties b/config.properties new file mode 100644 index 0000000..5331a43 --- /dev/null +++ b/config.properties @@ -0,0 +1,5 @@ +#Auth External Properties +#clientId= +#clientSecret= + +#authToken= \ No newline at end of file diff --git a/resources/config.properties b/resources/config.properties new file mode 100644 index 0000000..bffe582 --- /dev/null +++ b/resources/config.properties @@ -0,0 +1,5 @@ +#Auth Embedded Properties +#clientId= +#clientSecret= + +#authToken= \ No newline at end of file diff --git a/src/main/com/twitchcm/ClipsManager.java b/src/main/com/twitchcm/ClipsManager.java index bafe496..7a1e651 100644 --- a/src/main/com/twitchcm/ClipsManager.java +++ b/src/main/com/twitchcm/ClipsManager.java @@ -6,6 +6,7 @@ import main.com.twitchcm.filter.DashboardFetchClipsFilter; import main.com.twitchcm.filter.FetchClipsFilter; import main.com.twitchcm.filter.ProceedClipsFilter; +import main.com.twitchcm.tool.ConfigReader; import main.com.twitchcm.tool.TwitchWebConnection; import main.com.twitchcm.tool.Utils; @@ -15,14 +16,13 @@ import java.util.HashMap; import java.util.Map; -public class ClipsManager { +public class ClipsManager +{ - //can be blank and init later - private final static String CLIENT_ID = ""; - private final static String CLIENT_SECRET = ""; + private static String m_clientId = ConfigReader.getClientIdProp(); + private static String m_clientSecret = ConfigReader.getClientSecretProp(); - //can be blank and init later - private final static String AUTH_TOKEN = ""; + private static String m_authToken = ConfigReader.getAuthTokenProp(); //in case of using DB - DataSource.DATABASE should be used private final static DataSourceEnum DATA_SOURCE = DataSourceEnum.FILES; @@ -30,30 +30,32 @@ public class ClipsManager { private boolean m_allowOverwrite = false; private String m_rootDir = null; - private static final Mapm_auth = new HashMap<>(); + private static final Map m_auth = new HashMap<>(); //todo DataSource enum in the constructor args - public ClipsManager() { - m_auth.put(AuthJsonEnum.CLIENT_ID, CLIENT_ID); - m_auth.put(AuthJsonEnum.CLIENT_SECRET, CLIENT_SECRET); - - m_auth.put(AuthJsonEnum.AUTH_TOKEN, AUTH_TOKEN); + public ClipsManager() + { + setClientAuth( m_clientId, m_clientSecret ); + setAuthToken( m_authToken ); } public void setAuthToken(String _authToken) { - if (_authToken != null) { - m_auth.put(AuthJsonEnum.AUTH_TOKEN, _authToken); + if (_authToken != null) + { + m_auth.put( AuthJsonEnum.AUTH_TOKEN, _authToken ); } } public void setClientAuth(String _clientId, String _clientSecret) { - if(_clientId != null) { - m_auth.put(AuthJsonEnum.CLIENT_ID, _clientId); + if (_clientId != null) + { + m_auth.put( AuthJsonEnum.CLIENT_ID, _clientId ); } - if(_clientSecret != null){ - m_auth.put(AuthJsonEnum.CLIENT_SECRET, _clientSecret); + if (_clientSecret != null) + { + m_auth.put( AuthJsonEnum.CLIENT_SECRET, _clientSecret ); } } @@ -74,15 +76,18 @@ public String getCustomRootDir() public static Map getAuthCredential() { - if(!m_auth.containsKey(AuthJsonEnum.CLIENT_ID)) { - m_auth.put(AuthJsonEnum.CLIENT_ID, CLIENT_ID); + if (!m_auth.containsKey( AuthJsonEnum.CLIENT_ID )) + { + m_auth.put( AuthJsonEnum.CLIENT_ID, m_clientId ); } - if(!m_auth.containsKey(AuthJsonEnum.CLIENT_SECRET)) { - m_auth.put(AuthJsonEnum.CLIENT_SECRET, CLIENT_SECRET); + if (!m_auth.containsKey( AuthJsonEnum.CLIENT_SECRET )) + { + m_auth.put( AuthJsonEnum.CLIENT_SECRET, m_clientSecret ); } - if(!m_auth.containsKey(AuthJsonEnum.AUTH_TOKEN)) { - m_auth.put(AuthJsonEnum.AUTH_TOKEN, AUTH_TOKEN); + if (!m_auth.containsKey( AuthJsonEnum.AUTH_TOKEN )) + { + m_auth.put( AuthJsonEnum.AUTH_TOKEN, m_authToken ); } return m_auth; @@ -90,132 +95,143 @@ public static Map getAuthCredential() public void gameIdToName(String _gameId) throws LoginException { - if(_gameId != null) { - System.out.println(Utils.getGameName(_gameId, TwitchWebConnection.auth(m_auth))); + if (_gameId != null) + { + System.out.println( Utils.getGameName( _gameId, TwitchWebConnection.auth( m_auth ) ) ); } } public void gameNameToId(String _gameName) throws LoginException { - if(_gameName != null) { - System.out.println(Utils.getGameId(_gameName, TwitchWebConnection.auth(m_auth))); + if (_gameName != null) + { + System.out.println( Utils.getGameId( _gameName, TwitchWebConnection.auth( m_auth ) ) ); } } public void channelIdToName(String _channelId) throws LoginException { - if(_channelId != null) { - System.out.println(Utils.getBroadcasterLogin(_channelId, TwitchWebConnection.auth(m_auth))); + if (_channelId != null) + { + System.out.println( Utils.getBroadcasterLogin( _channelId, TwitchWebConnection.auth( m_auth ) ) ); } } public void channelNameToId(String _channelName) throws LoginException { - if(_channelName != null) { - System.out.println(Utils.getBroadcasterId(_channelName, TwitchWebConnection.auth(m_auth))); + if (_channelName != null) + { + System.out.println( Utils.getBroadcasterId( _channelName, TwitchWebConnection.auth( m_auth ) ) ); } } private void setRootDir(ClipsActionAbstract _clipsActionObj) { - if(m_rootDir != null) { - _clipsActionObj.setRootDir(m_rootDir); + if (m_rootDir != null) + { + _clipsActionObj.setRootDir( m_rootDir ); } } public void fetchTopClips(String _broadcasterId) { - fetchTopClips(new FetchClipsFilter(_broadcasterId)); + fetchTopClips( new FetchClipsFilter( _broadcasterId ) ); } public void fetchTopClips(FetchClipsFilter _filter) { - ClipsFetcher clipsFetcher = new ClipsFetcher(DATA_SOURCE, m_allowOverwrite); - setRootDir(clipsFetcher); - clipsFetcher.setAuth(m_auth); - clipsFetcher.setFetchFilter(_filter); + ClipsFetcher clipsFetcher = new ClipsFetcher( DATA_SOURCE, m_allowOverwrite ); + setRootDir( clipsFetcher ); + clipsFetcher.setAuth( m_auth ); + clipsFetcher.setFetchFilter( _filter ); clipsFetcher.fetchTopClips(); } public void fetchClips(FetchClipsFilter _filter) { - ClipsFetcher clipsFetcher = new ClipsFetcher(DATA_SOURCE, m_allowOverwrite); - setRootDir(clipsFetcher); - clipsFetcher.setAuth(m_auth); - clipsFetcher.setFetchFilter(_filter); + ClipsFetcher clipsFetcher = new ClipsFetcher( DATA_SOURCE, m_allowOverwrite ); + setRootDir( clipsFetcher ); + clipsFetcher.setAuth( m_auth ); + clipsFetcher.setFetchFilter( _filter ); clipsFetcher.fetchClips(); } public void fetchDashboardClips(DashboardFetchClipsFilter _filter) { - DashboardClipsFetcher clipsFetcher = new DashboardClipsFetcher(DATA_SOURCE, m_allowOverwrite); - setRootDir(clipsFetcher); - clipsFetcher.setAuth(m_auth); - clipsFetcher.setFetchFilter(_filter); + DashboardClipsFetcher clipsFetcher = new DashboardClipsFetcher( DATA_SOURCE, m_allowOverwrite ); + setRootDir( clipsFetcher ); + clipsFetcher.setAuth( m_auth ); + clipsFetcher.setFetchFilter( _filter ); clipsFetcher.fetchClips(); } public void distinctFetchedClips() { - ClipsFetcher clipsFetcher = new ClipsFetcher(DATA_SOURCE, false); - setRootDir(clipsFetcher); + ClipsFetcher clipsFetcher = new ClipsFetcher( DATA_SOURCE, false ); + setRootDir( clipsFetcher ); clipsFetcher.distinctClips(); } public void downloadClips(String _eachTime, ProceedClipsFilter _proceedFilter) { - try { - downloadClips(Integer.parseInt(_eachTime), _proceedFilter); - }catch (NumberFormatException e) + try + { + downloadClips( Integer.parseInt( _eachTime ), _proceedFilter ); + } + catch (NumberFormatException e) { - System.err.println(e.getMessage()); + System.err.println( e.getMessage() ); } } public void downloadClips(int _eachTime, ProceedClipsFilter _proceedFilter) { - ClipsDownloader clipsDownloader = new ClipsDownloader(DATA_SOURCE, m_allowOverwrite); - setRootDir(clipsDownloader); - clipsDownloader.setProceedFilter(_proceedFilter); - clipsDownloader.downloadClips(_eachTime); + ClipsDownloader clipsDownloader = new ClipsDownloader( DATA_SOURCE, m_allowOverwrite ); + setRootDir( clipsDownloader ); + clipsDownloader.setProceedFilter( _proceedFilter ); + clipsDownloader.downloadClips( _eachTime ); } public void deleteClips(String _eachTime, ProceedClipsFilter _proceedFilter) { - try { - deleteClips(Integer.parseInt(_eachTime), _proceedFilter); - }catch (NumberFormatException e) + try { - System.err.println(e.getMessage()); + deleteClips( Integer.parseInt( _eachTime ), _proceedFilter ); + } + catch (NumberFormatException e) + { + System.err.println( e.getMessage() ); } } public void deleteClips(int _eachTime, ProceedClipsFilter _proceedFilter) { - ClipsDeleter clipsDeleter = new ClipsDeleter(DATA_SOURCE, m_allowOverwrite); - setRootDir(clipsDeleter); - clipsDeleter.setAuth(m_auth); - clipsDeleter.setProceedFilter(_proceedFilter); - clipsDeleter.deleteClips(_eachTime); + ClipsDeleter clipsDeleter = new ClipsDeleter( DATA_SOURCE, m_allowOverwrite ); + setRootDir( clipsDeleter ); + clipsDeleter.setAuth( m_auth ); + clipsDeleter.setProceedFilter( _proceedFilter ); + clipsDeleter.deleteClips( _eachTime ); } public void createClip(String _vodId, String _title, String _vodTime, String _durationSec) { - try { - createClip(_vodId, _title, - (float) Duration.parse(_vodTime).toMillis()/1000, - (float) Duration.parse(_durationSec).toMillis()/1000); - }catch (DateTimeParseException e) + try + { + createClip( _vodId, _title, + (float) Duration.parse( _vodTime ).toMillis() / 1000, + (float) Duration.parse( _durationSec ).toMillis() / 1000 ); + } + catch (DateTimeParseException e) { - System.err.println(e.getMessage()); + System.err.println( e.getMessage() ); } } public void createClip(String _vodId, String _title, float _vodTimeSec, float _durationSec) { - ClipsCreator clipsCreator = new ClipsCreator(DATA_SOURCE, m_allowOverwrite); - setRootDir(clipsCreator); - clipsCreator.setAuth(m_auth); - clipsCreator.createClip(_vodId, _title, _vodTimeSec, _durationSec); + ClipsCreator clipsCreator = new ClipsCreator( DATA_SOURCE, m_allowOverwrite ); + setRootDir( clipsCreator ); + clipsCreator.setAuth( m_auth ); + clipsCreator.createClip( _vodId, _title, _vodTimeSec, _durationSec ); } } diff --git a/src/main/com/twitchcm/enums/InputArgsEnum.java b/src/main/com/twitchcm/enums/InputArgsEnum.java index 95ecded..6e88095 100644 --- a/src/main/com/twitchcm/enums/InputArgsEnum.java +++ b/src/main/com/twitchcm/enums/InputArgsEnum.java @@ -8,7 +8,7 @@ public enum InputArgsEnum { //Auth CLIENT_ID("clientId", "clientId", "API client id", true), CLIENT_SECRET("clientSecret", "clientSecret", "API client secret", true), - AUTH_TOKEN("auth", "authToken", "auth-token from cookies", true), + AUTH_TOKEN("authToken", "authToken", "auth-token from cookies", true), //FetchFilter BROADCASTER_ID("chId", "broadcasterId", "Channel id (user id) of a broadcaster from which the clip was created. Channel id can be obtained by using chNameToId Util", true), diff --git a/src/main/com/twitchcm/tool/ConfigReader.java b/src/main/com/twitchcm/tool/ConfigReader.java new file mode 100644 index 0000000..8ff10ed --- /dev/null +++ b/src/main/com/twitchcm/tool/ConfigReader.java @@ -0,0 +1,167 @@ +package main.com.twitchcm.tool; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Objects; +import java.util.Properties; + +public final class ConfigReader +{ + public enum ConfigEnum + { + CLIENT_ID( "clientId" ), + CLIENT_SECRET( "clientSecret" ), + + AUTH_TOKEN( "authToken" ); //from cookies + + private final String m_jsonKey; + + ConfigEnum(String _jsonKey) + { + m_jsonKey = _jsonKey; + } + + @Override + public String toString() + { + return m_jsonKey; + } + } + + private static final String PROP_FILE = "config.properties"; + private static final String EXT_PROP_FILE = System.getProperty( "user.dir" ) + "/" + PROP_FILE; + + private static String m_clientIdProp; + private static String m_clientSecretProp; + private static String m_authTokenProp; + + private static boolean m_is_read = false; + + private ConfigReader() + { + //singleton + } + + private static void read() + { + readEmbedded(); + readExternal(); + + m_is_read = true; + } + + private static void readEmbedded() //primary config + { + InputStream inputStream = null; + + try + { + Properties prop = new Properties(); + + inputStream = ConfigReader.class.getClassLoader().getResourceAsStream( PROP_FILE ); + + if (inputStream != null) + { + prop.load( inputStream ); + } + else + { + throw new FileNotFoundException( "Property file '" + PROP_FILE + "' not found in the classpath" ); + } + + m_clientIdProp = prop.getProperty( ConfigEnum.CLIENT_ID.toString() ); + m_clientSecretProp = prop.getProperty( ConfigEnum.CLIENT_SECRET.toString() ); + m_authTokenProp = prop.getProperty( ConfigEnum.AUTH_TOKEN.toString() ); + } + catch (Exception e) + { + System.out.println( "Exception: " + e ); + } + finally + { + if (inputStream != null) + { + try + { + inputStream.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + } + + private static void readExternal() + { + InputStream inputStream = null; + + try + { + Properties prop = new Properties(); + + try + { + inputStream = new FileInputStream( EXT_PROP_FILE ); + prop.load( inputStream ); + } + catch (FileNotFoundException e) + { + System.err.println( "Warning! Property file '" + EXT_PROP_FILE + "' not found" ); + return; + } + + m_clientIdProp = Objects.isNull( m_clientIdProp ) + ? prop.getProperty( ConfigEnum.CLIENT_ID.toString() ) : m_clientIdProp; + m_clientSecretProp = Objects.isNull( m_clientSecretProp ) + ? prop.getProperty( ConfigEnum.CLIENT_SECRET.toString() ) : m_clientSecretProp; + m_authTokenProp = Objects.isNull( m_authTokenProp ) + ? prop.getProperty( ConfigEnum.AUTH_TOKEN.toString() ) : m_authTokenProp; + } + catch (Exception e) + { + System.out.println( "Exception: " + e ); + } + finally + { + if (inputStream != null) + { + try + { + inputStream.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + } + + public static String getClientIdProp() + { + if (!m_is_read) + read(); + + return m_clientIdProp; + } + + public static String getClientSecretProp() + { + if (!m_is_read) + read(); + + return m_clientSecretProp; + } + + public static String getAuthTokenProp() + { + if (!m_is_read) + read(); + + return m_authTokenProp; + } +}