2017-04-17 00:58:49 +02:00
package cloudControllerInstances ;
2017-05-04 22:07:50 +02:00
import java.io.FileInputStream ;
2017-04-17 23:37:06 +02:00
import java.io.FileOutputStream ;
import java.io.IOException ;
import java.io.InputStream ;
import java.io.InputStreamReader ;
import java.io.OutputStream ;
import java.util.ArrayList ;
import java.util.Collections ;
import java.util.List ;
import org.apache.commons.io.FileUtils ;
2017-04-17 00:58:49 +02:00
import com.google.api.client.auth.oauth2.Credential ;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp ;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver ;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow ;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets ;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport ;
import com.google.api.client.http.FileContent ;
import com.google.api.client.http.HttpTransport ;
import com.google.api.client.json.JsonFactory ;
2017-04-17 23:37:06 +02:00
import com.google.api.client.json.jackson2.JacksonFactory ;
2017-04-17 00:58:49 +02:00
import com.google.api.client.util.DateTime ;
import com.google.api.client.util.store.FileDataStoreFactory ;
import com.google.api.services.drive.Drive ;
import com.google.api.services.drive.Drive.Files ;
2017-04-17 23:37:06 +02:00
import com.google.api.services.drive.DriveScopes ;
import com.google.api.services.drive.model.File ;
import com.google.api.services.drive.model.FileList ;
2017-04-17 00:58:49 +02:00
public class GoogleDriveController {
Drive service ;
private String cemuDirectory ;
private String folderID ;
private ArrayList < java . io . File > localSavegames = new ArrayList < > ( ) ;
private ArrayList < File > cloudSavegames = new ArrayList < > ( ) ;
private ArrayList < String > localSavegamesName = new ArrayList < > ( ) ;
private ArrayList < String > cloudSavegamesName = new ArrayList < > ( ) ;
private final String APPLICATION_NAME = " cemu_Ui Drive API Controller " ;
2017-04-25 22:16:30 +02:00
//Directory to store user credentials for this application
2017-04-17 00:58:49 +02:00
private final java . io . File DATA_STORE_DIR = new java . io . File ( System . getProperty ( " user.home " ) , " .credentials/cemu_UI_credential " ) ;
2017-04-25 22:16:30 +02:00
//Global instance of the {@link FileDataStoreFactory}
2017-04-17 00:58:49 +02:00
private FileDataStoreFactory DATA_STORE_FACTORY ;
2017-04-25 22:16:30 +02:00
//Global instance of the JSON factory
2017-04-17 00:58:49 +02:00
private final JsonFactory JSON_FACTORY = JacksonFactory . getDefaultInstance ( ) ;
2017-04-25 22:16:30 +02:00
//Global instance of the HTTP transport
2017-04-17 00:58:49 +02:00
private HttpTransport HTTP_TRANSPORT ;
2017-04-25 22:16:30 +02:00
/ * * If modifying these scopes , delete your previously saved credentials
2017-04-17 00:58:49 +02:00
* at ~ / . credentials / cemu_UI_credential
* /
private final java . util . Collection < String > SCOPES = DriveScopes . all ( ) ;
public GoogleDriveController ( ) {
try {
HTTP_TRANSPORT = GoogleNetHttpTransport . newTrustedTransport ( ) ;
DATA_STORE_FACTORY = new FileDataStoreFactory ( DATA_STORE_DIR ) ;
folderID = " " ;
} catch ( Throwable t ) {
t . printStackTrace ( ) ;
System . exit ( 1 ) ;
}
}
/ * *
* Creates an authorized Credential object .
* @return an authorized Credential object .
* @throws IOException
* /
public Credential authorize ( ) throws IOException {
// Load client secrets.
InputStream in = getClass ( ) . getClassLoader ( ) . getResourceAsStream ( " recources/client_secret.json " ) ;
GoogleClientSecrets clientSecrets = GoogleClientSecrets . load ( JSON_FACTORY , new InputStreamReader ( in ) ) ;
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow =
new GoogleAuthorizationCodeFlow . Builder ( HTTP_TRANSPORT , JSON_FACTORY , clientSecrets , SCOPES )
. setDataStoreFactory ( DATA_STORE_FACTORY )
. setAccessType ( " offline " )
. build ( ) ;
Credential credential = new AuthorizationCodeInstalledApp ( flow , new LocalServerReceiver ( ) ) . authorize ( " user " ) ;
System . out . println ( " Credentials saved to " + DATA_STORE_DIR . getAbsolutePath ( ) ) ;
return credential ;
}
/ * *
* Build and return an authorized Drive client service .
* @return an authorized Drive client service
* @throws IOException
* /
2017-04-25 22:16:30 +02:00
public Drive getDriveService ( ) throws IOException {
2017-04-17 00:58:49 +02:00
Credential credential = authorize ( ) ;
return new Drive . Builder ( HTTP_TRANSPORT , JSON_FACTORY , credential )
. setApplicationName ( APPLICATION_NAME )
. build ( ) ;
}
public void main ( String cemuDirectory ) throws IOException {
service = getDriveService ( ) ;
this . cemuDirectory = cemuDirectory ;
}
2017-04-25 22:16:30 +02:00
public void sync ( String cemuDirectory ) throws IOException {
getLocalSavegames ( ) ;
2017-05-04 22:07:50 +02:00
getCloudSavegames ( ) ;
2017-04-25 22:16:30 +02:00
2017-05-04 22:07:50 +02:00
// download files from cloud which don't exist locally
for ( int i = 0 ; i < cloudSavegames . size ( ) ; i + + ) {
2017-04-25 22:16:30 +02:00
2017-05-04 22:07:50 +02:00
// if the file exists locally, check which one is newer
if ( localSavegamesName . contains ( cloudSavegames . get ( i ) . getName ( ) ) ) {
2017-04-25 22:16:30 +02:00
2017-05-04 22:07:50 +02:00
int localSavegamesNumber = localSavegamesName . indexOf ( cloudSavegames . get ( i ) . getName ( ) ) ;
long localModified = new DateTime ( localSavegames . get ( localSavegamesNumber ) . lastModified ( ) ) . getValue ( ) ;
long cloudModified = cloudSavegames . get ( i ) . getModifiedTime ( ) . getValue ( ) ;
2017-05-07 19:57:55 +02:00
FileInputStream fis = new FileInputStream ( localSavegames . get ( localSavegamesNumber ) ) ;
2017-05-04 22:07:50 +02:00
if ( cloudSavegames . get ( i ) . getMd5Checksum ( ) . equals ( org . apache . commons . codec . digest . DigestUtils . md5Hex ( fis ) ) ) {
System . out . println ( " both files are the same, nothing to do " ) ;
} else {
if ( localModified > = cloudModified ) {
System . out . print ( " local is newer, " ) ;
2017-04-25 22:16:30 +02:00
updateFile ( cloudSavegames . get ( i ) , localSavegames . get ( localSavegamesNumber ) ) ;
} else {
2017-05-04 22:07:50 +02:00
System . out . print ( " cloud is newer, " ) ;
2017-04-25 22:16:30 +02:00
downloadFile ( cloudSavegames . get ( i ) ) ;
}
}
2017-05-04 22:07:50 +02:00
} else {
System . out . print ( " file doesn't exist locally, " ) ;
downloadFile ( cloudSavegames . get ( i ) ) ;
2017-04-25 22:16:30 +02:00
}
2017-05-04 22:07:50 +02:00
}
2017-04-25 22:16:30 +02:00
2017-05-04 22:07:50 +02:00
// upload file to cloud which don't exist in the cloud
for ( int j = 0 ; j < localSavegames . size ( ) ; j + + ) {
if ( ! cloudSavegamesName . contains ( localSavegamesName . get ( j ) ) ) {
2017-05-04 22:32:25 +02:00
System . out . print ( " file doesn't exist in the cloud, " ) ;
2017-05-04 22:07:50 +02:00
uploadFile ( localSavegames . get ( j ) ) ;
2017-04-25 22:16:30 +02:00
}
}
}
//create a folder in google drive
2017-05-04 22:07:50 +02:00
public void creatFolder ( ) throws IOException {
2017-04-17 00:58:49 +02:00
System . out . println ( " creating new folder " ) ;
File fileMetadata = new File ( ) ;
fileMetadata . setName ( " cemu_savegames " ) ;
fileMetadata . setMimeType ( " application/vnd.google-apps.folder " ) ;
2017-04-25 22:16:30 +02:00
File file = service . files ( ) . create ( fileMetadata ) . setFields ( " id " ) . execute ( ) ;
2017-04-17 00:58:49 +02:00
System . out . println ( " Folder ID: " + file . getId ( ) ) ;
folderID = file . getId ( ) ;
2017-04-25 22:16:30 +02:00
}
//check if folder already exist
2017-05-04 22:07:50 +02:00
public boolean checkFolder ( ) {
2017-04-17 00:58:49 +02:00
try {
Files . List request = service . files ( ) . list ( ) . setQ ( " mimeType = 'application/vnd.google-apps.folder' and name = 'cemu_savegames' " ) ;
FileList files = request . execute ( ) ;
if ( files . getFiles ( ) . size ( ) = = 0 ) {
return false ;
} else {
return true ;
}
} catch ( IOException e ) {
e . printStackTrace ( ) ;
return false ;
}
2017-04-25 22:16:30 +02:00
}
//reading all local savegames
private void getLocalSavegames ( ) throws IOException {
java . io . File dir = new java . io . File ( cemuDirectory + " /mlc01/emulatorSave " ) ;
String [ ] extensions = new String [ ] { " dat " } ;
2017-05-24 19:26:36 +02:00
localSavegames . removeAll ( localSavegames ) ;
localSavegamesName . removeAll ( localSavegamesName ) ;
2017-05-07 19:57:55 +02:00
System . out . println ( " Getting all .dat files in " + dir . getCanonicalPath ( ) + " including those in subdirectories " ) ;
2017-05-24 19:26:36 +02:00
List < java . io . File > files = ( List < java . io . File > ) FileUtils . listFiles ( dir , extensions , true ) ;
2017-04-25 22:16:30 +02:00
for ( java . io . File file : files ) {
2017-04-17 00:58:49 +02:00
localSavegamesName . add ( file . getParentFile ( ) . getName ( ) + " _ " + file . getName ( ) ) ;
localSavegames . add ( file ) ;
2017-04-25 22:16:30 +02:00
}
}
//reading all cloud savegames
private void getCloudSavegames ( ) throws IOException {
2017-05-04 22:07:50 +02:00
System . out . println ( " getting all cloud savegames " ) ;
2017-05-24 19:26:36 +02:00
cloudSavegames . removeAll ( cloudSavegames ) ;
cloudSavegamesName . removeAll ( cloudSavegamesName ) ;
2017-05-04 22:07:50 +02:00
Files . List request = service . files ( ) . list ( ) . setQ ( " fileExtension = 'dat' and ' " + folderID + " ' in parents " ) . setFields ( " nextPageToken, files(id, name, size, modifiedTime, createdTime, md5Checksum) " ) ;
2017-04-25 22:16:30 +02:00
FileList files = request . execute ( ) ;
2017-04-17 00:58:49 +02:00
2017-04-25 22:16:30 +02:00
for ( File file : files . getFiles ( ) ) {
cloudSavegamesName . add ( file . getName ( ) ) ;
cloudSavegames . add ( file ) ;
}
}
//upload a file to the cloud from the local savegames folder
public void uploadFile ( java . io . File uploadFile ) throws IOException {
2017-05-04 22:32:25 +02:00
System . out . println ( " uploading " + uploadFile . getName ( ) + " ... " ) ;
2017-04-17 00:58:49 +02:00
File fileMetadata = new File ( ) ;
fileMetadata . setName ( uploadFile . getParentFile ( ) . getName ( ) + " _ " + uploadFile . getName ( ) ) ;
fileMetadata . setParents ( Collections . singletonList ( folderID ) ) ;
fileMetadata . setModifiedTime ( new DateTime ( uploadFile . lastModified ( ) ) ) ;
FileContent mediaContent = new FileContent ( " " , uploadFile ) ;
File file = service . files ( ) . create ( fileMetadata , mediaContent ) . setFields ( " id, parents " ) . execute ( ) ;
2017-05-07 19:57:55 +02:00
System . out . println ( " upload successfull, File ID: " + file . getId ( ) ) ;
2017-04-25 22:16:30 +02:00
}
2017-04-17 00:58:49 +02:00
2017-04-25 22:16:30 +02:00
//download a file from the cloud to the local savegames folder
private void downloadFile ( File downloadFile ) throws IOException {
2017-05-04 22:07:50 +02:00
System . out . print ( " downloading " + downloadFile . getName ( ) + " ... " ) ;
2017-05-24 19:26:36 +02:00
java . io . File directory = new java . io . File ( cemuDirectory + " /mlc01/emulatorSave/ " + downloadFile . getName ( ) . substring ( 0 , 8 ) ) ;
2017-04-25 22:16:30 +02:00
String file = downloadFile . getName ( ) . substring ( 9 , downloadFile . getName ( ) . length ( ) ) ;
2017-05-24 19:26:36 +02:00
if ( ! directory . exists ( ) ) {
System . out . print ( " dir dosent exist... " ) ;
directory . mkdir ( ) ;
2017-04-25 22:16:30 +02:00
}
2017-04-17 00:58:49 +02:00
2017-05-24 19:26:36 +02:00
OutputStream outputStream = new FileOutputStream ( directory + " / " + file ) ;
2017-04-25 22:16:30 +02:00
service . files ( ) . get ( downloadFile . getId ( ) ) . executeMediaAndDownloadTo ( outputStream ) ;
2017-05-24 19:26:36 +02:00
outputStream . close ( ) ;
2017-04-25 22:16:30 +02:00
System . out . println ( " done " ) ;
}
//update a file in the cloud, by deleting the old one and uploading an new with the same id
private void updateFile ( File oldFile , java . io . File newFile ) throws IOException {
2017-05-04 22:07:50 +02:00
System . out . println ( " updating " + oldFile . getName ( ) + " ... " ) ;
service . files ( ) . delete ( oldFile . getId ( ) ) . execute ( ) ; //deleting old file
2017-04-17 00:58:49 +02:00
2017-04-25 22:16:30 +02:00
//uploading new file
File fileMetadata = new File ( ) ;
fileMetadata . setName ( newFile . getParentFile ( ) . getName ( ) + " _ " + newFile . getName ( ) ) ;
fileMetadata . setParents ( Collections . singletonList ( folderID ) ) ;
fileMetadata . setModifiedTime ( new DateTime ( newFile . lastModified ( ) ) ) ;
2017-04-17 23:37:06 +02:00
2017-04-25 22:16:30 +02:00
FileContent mediaContent = new FileContent ( " " , newFile ) ;
File file = service . files ( ) . create ( fileMetadata , mediaContent ) . setFields ( " id, parents " ) . execute ( ) ;
System . out . println ( " File ID: " + file . getId ( ) ) ;
2017-04-17 00:58:49 +02:00
}
2017-05-04 22:07:50 +02:00
public void uploadAllFiles ( ) {
2017-05-07 19:57:55 +02:00
try {
getLocalSavegames ( ) ;
System . out . println ( " uploading " + localSavegames . size ( ) + " files... " ) ;
for ( int i = 0 ; i < localSavegames . size ( ) ; i + + ) {
uploadFile ( localSavegames . get ( i ) ) ;
}
2017-05-24 19:26:36 +02:00
System . out . println ( " finished uploading all files! " ) ;
2017-05-07 19:57:55 +02:00
} catch ( IOException e ) {
//Auto-generated catch block
e . printStackTrace ( ) ;
}
}
2017-05-04 22:07:50 +02:00
2017-04-17 00:58:49 +02:00
public String getFolderID ( ) {
return folderID ;
}
public void setFolderID ( String folderID ) {
this . folderID = folderID ;
}
}