using Google.Apis.Auth.OAuth2; using Google.Apis.Sheets.v4; using Google.Apis.Sheets.v4.Data; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using System.Linq; using UnityEditor; public static class GoogleSheetsHelper { static readonly string JsonLocation = "Assets/Code/Localization/Editor/"; static readonly string JsonFile = "clients_secrets.json"; // No use in actual build. This shit has owner permissions. static readonly string[] Scopes = { SheetsService.Scope.Spreadsheets }; static readonly string ApplicationName = "Localization"; static readonly string SpreadsheetId = "1O_Uyml6J_dx7Vt7DLHTTnJqLBXr0ol_xS5pPCjbR1ks"; static readonly string cutscenesheet = "mainsheet"; static SheetsService service; static char LanguageRange = (char)('A' + Localization.LanguageCount); static GoogleSheetsHelper() { GoogleCredential credential; using (var stream = new FileStream(System.IO.Path.Combine(JsonLocation, JsonFile), FileMode.Open, FileAccess.Read)) { credential = GoogleCredential.FromStream(stream) .CreateScoped(Scopes); } service = new SheetsService(new Google.Apis.Services.BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = ApplicationName } ); } #region Push public static void Push() { var locals = ReadLocalizaiton(); var sheets = ReadGoogleSheets(); // Create foreach(var item in locals){ string[] list; if (!sheets.TryGetValue(item.Key, out list)){ list = new string[Localization.LanguageCount]; sheets.Add(item.Key, list); } list[0] = item.Value; } string message = string.Format("Sending {0} keys.", sheets.Keys.Count); if (EditorUtility.DisplayDialog("Confirm Push?", message, "Push", "Do Not Push")) { // Sort var parse = sheets.ToList().Select(s => (s.Key, s.Value)).ToList(); parse.Sort((pair1, pair2) => pair1.Key.CompareTo(pair2.Key)); string prev = string.Empty; for(var i = 0; i < parse.Count; i++){ var n = parse[i].Key; if (string.IsNullOrWhiteSpace(n)) continue; var t = n.Substring(0, n.IndexOf('_')); if (!string.IsNullOrWhiteSpace(prev) && t != prev){ parse.Insert(i, (" ", new string[Localization.LanguageCount])); i++; } prev = t; } SendToGoogleSheets(parse); } } public static void Pull(){ var sheets = ReadGoogleSheets(); if (EditorUtility.DisplayDialog("Confirm Pull?", "", "Pull", "Do not Pull")){ var serializedObject = new SerializedObject(Localization.Instance); serializedObject.Update(); var langauges = Localization.Langauges; for (var i = 0; i < langauges.Length; i++){ var langauge = (LocalizationLanguage)langauges.GetValue(i); var field = string.Format("{0}Locals", langauge.ToString().ToLowerInvariant()); var prop = serializedObject.FindProperty(field); var s = 0; foreach(var set in sheets){ if (s >= prop.arraySize){ prop.InsertArrayElementAtIndex(s); } SerializedProperty element = prop.GetArrayElementAtIndex(s); SerializedProperty keyProp = element.FindPropertyRelative("key"); SerializedProperty textProp = element.FindPropertyRelative("text"); keyProp.stringValue = set.Key; textProp.stringValue = set.Value[i]; s++; } } serializedObject.ApplyModifiedProperties(); } } #endregion #region Assets public static Dictionary ReadLocalizaiton(){ var dict = new Dictionary(); var l = Localization.Instance; var locals = l.englishLocals; for(var j = 0; j < locals.Length; j++){ var item = locals[j]; dict.Add(item.key, item.text); } return dict; } #endregion #region Google Sheets Read /// /// Returns a dictionary of all keys found with their respective localized text. /// /// public static Dictionary ReadGoogleSheets() { var dict = new Dictionary(); // Ask google sheets var range = string.Format("{0}!A2:{1}", cutscenesheet, LanguageRange); var request = service.Spreadsheets.Values.Get(SpreadsheetId, range); var response = request.Execute(); var values = response.Values; // If received valid response if (values != null && values.Count > 0) { foreach (var row in values) { if (row.Count > 0) { var key = row[0] as string; if (string.IsNullOrWhiteSpace(key)) continue; var list = new string[Localization.LanguageCount]; for (var i = 0; i < list.Length; i++){ string text; if (i + 1 < row.Count) text = row[i + 1] as string; else text = string.Empty; list[i] = text; } dict.Add(key, list); } } } return dict; } #endregion #region Google Sheets Write /// /// Writes to google sheets. /// /// public static void SendToGoogleSheets(List<(string key, string[] texts)> locals) { var columns = CreateGoogleSheetsColumns(locals); ClearGoogleSheets(); WriteToGoogleSheets(columns); } /// /// Creates a tabled list to be send with . /// /// /// public static List> CreateGoogleSheetsColumns(List<(string key, string[] texts)> locals) { // Create list to send to google sheets var columns = new List>(); // Top part with the langauges var header = new List(); header.Add("Keys"); var langauges = Localization.Langauges; foreach(LocalizationLanguage e in langauges) { header.Add(e.ToString()); } columns.Add(header); foreach (var pair in locals) { var key = pair.key; var texts = pair.texts; var row = new List(); row.Add(key); foreach(var t in texts){ if (t != null) row.Add(t); } columns.Add(row); } return columns; } /// /// Wipes it clean. /// public static void ClearGoogleSheets() { var clearRange = new ClearValuesRequest(); var clearRequest = service.Spreadsheets.Values.Clear(clearRange, SpreadsheetId, cutscenesheet); var clearReponse = clearRequest.Execute(); Debug.Log("Clearing google sheets"); } /// /// Overwrites the sheet with . /// /// public static void WriteToGoogleSheets(List> columns) { // Create range var range = string.Format("{0}!A1:{1}", cutscenesheet, LanguageRange); var valueRange = new ValueRange(); valueRange.Values = columns; // Send to Google Sheets var updateRequest = service.Spreadsheets.Values.Update(valueRange, SpreadsheetId, range); updateRequest.ValueInputOption = SpreadsheetsResource.ValuesResource.UpdateRequest.ValueInputOptionEnum.USERENTERED; var updateReponse = updateRequest.Execute(); Debug.Log("Finished syncing to google sheets"); } #endregion }