157 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System.Collections;
 | |
| using System.Collections.Generic;
 | |
| using System.IO;
 | |
| using System.Linq;
 | |
| using System.Security.Cryptography.X509Certificates;
 | |
| using System.Text;
 | |
| using System.Threading;
 | |
| using Google.Apis.Auth.OAuth2;
 | |
| using Google.Apis.Services;
 | |
| using Google.Apis.Sheets.v4;
 | |
| using Google.Apis.Util.Store;
 | |
| using UnityEngine;
 | |
| 
 | |
| #region Editor
 | |
| #if UNITY_EDITOR
 | |
| using UnityEditor;
 | |
| 
 | |
| public static partial class DialogueDatabase
 | |
| {
 | |
|     
 | |
|     public static string EDITOR_DialogueFile =>
 | |
|         Path.Combine(Application.dataPath, "Data", "Dialogue", DIALOGUE_FILENAME);
 | |
|     
 | |
|     // TODO: neither of these should be in the repository! ideally, move them behind secure
 | |
|     // gitlab variables before there is too much data at risk
 | |
|     private const string SPREADSHEET_ID = "1H42653xGbKLxbsDzz7CSR0iaNMz1hU42LX5hWiFtn-Y";
 | |
|     private const string API_KEY = "AIzaSyD-tKzeKpAj5sFnbXbj2k4H2RQxipw8B8s";
 | |
|     private const string SERVICE_ACCOUNT_EMAIL = "gitlab-runner-dialogue-import@revival-304616.iam.gserviceaccount.com";
 | |
|     private const string CERTIFICATE_NAME = "revival-304616-7f150d13c408.p12";
 | |
|     
 | |
|     private static string _workFolder => Path.Combine(Application.dataPath, "Data", "Dialogue");
 | |
|     private static string _certificateFile => Path.Combine(_workFolder, CERTIFICATE_NAME);
 | |
| 
 | |
|     // makes a web request via google 
 | |
|     // returns 0 on success
 | |
|     public static int Import()
 | |
|     {
 | |
|         var certificate = new X509Certificate2(_certificateFile, "notasecret", X509KeyStorageFlags.Exportable);
 | |
| 
 | |
|         var credential = new ServiceAccountCredential(
 | |
|             new ServiceAccountCredential.Initializer(SERVICE_ACCOUNT_EMAIL)
 | |
|             {
 | |
|                 Scopes = new[] {SheetsService.Scope.SpreadsheetsReadonly}
 | |
|             }.FromCertificate(certificate));
 | |
| 
 | |
|         var service = new SheetsService(new BaseClientService.Initializer()
 | |
|         {
 | |
|             HttpClientInitializer = credential,
 | |
|             ApplicationName = "Kernel Panic - Revival Dialogue Importer",
 | |
|             ApiKey = API_KEY
 | |
|         });
 | |
| 
 | |
|         // first two columns, ignore first row
 | |
|         var range = "Sheet1!A2:B";
 | |
|         var request = service.Spreadsheets.Values.Get(SPREADSHEET_ID, range);
 | |
| 
 | |
|         var response = request.Execute();
 | |
|         var values = response.Values;
 | |
| 
 | |
|         if (values == null || values.Count == 0)
 | |
|         {
 | |
|             Debug.LogError("no data");
 | |
|             return 1;
 | |
|         }
 | |
| 
 | |
|         Debug.Log($":: importing dialogue");
 | |
|         var sb = new StringBuilder();
 | |
|         var lines = 0;
 | |
|         foreach (var row in values)
 | |
|         {
 | |
|             if (row.Count != 2)
 | |
|             {
 | |
|                 Debug.Log($":: skipping non-matching line: {lines}: {(row.Count == 0 ? "empty" : string.Join(",", row))}");
 | |
|                 continue;
 | |
|             }
 | |
|             
 | |
|             sb.AppendLine($"{row[0]}{SPLIT_CHAR}{row[1]}");
 | |
|             lines++;
 | |
|         }
 | |
|         Debug.Log($":: imported {lines} lines of dialogue\n{sb}");
 | |
| 
 | |
|         File.WriteAllText(EDITOR_DialogueFile, sb.ToString());
 | |
|         if (!File.Exists(EDITOR_DialogueFile))
 | |
|         {
 | |
|             Debug.LogError($":: import failed: file doesn't exist: {EDITOR_DialogueFile}");
 | |
|             return 1;
 | |
|         }
 | |
| 
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     [MenuItem("ktyl/Import Dialogue")]
 | |
|     private static void ImportDialogueMenuItem()
 | |
|     {
 | |
|         Import();
 | |
|     }
 | |
| }
 | |
| 
 | |
| #endif
 | |
| #endregion
 | |
| 
 | |
| public static partial class DialogueDatabase
 | |
| {
 | |
|     private const char SPLIT_CHAR = '|';
 | |
|     
 | |
|     public const string DIALOGUE_FILENAME = "dialogue.data";
 | |
| 
 | |
|     public static string DialogueFile
 | |
|     {
 | |
|         get
 | |
|         {
 | |
| #if UNITY_EDITOR
 | |
|             // ensure file exists and run import if necessary
 | |
|             if (!File.Exists(EDITOR_DialogueFile) && Import() != 0) return null;
 | |
|             
 | |
|             return EDITOR_DialogueFile;
 | |
| #else
 | |
|             return Path.Combine(Application.dataPath, DIALOGUE_FILENAME);
 | |
| #endif
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     static DialogueDatabase()
 | |
|     {
 | |
|         Debug.Log($":: building dialogue database from file at {DialogueFile}");
 | |
| 
 | |
|         int count = 0;
 | |
|         foreach (var line in File.ReadLines(DialogueFile))
 | |
|         {
 | |
|             var parts = line.Split(SPLIT_CHAR);
 | |
| 
 | |
|             var key = parts[0];
 | |
|             var text = parts[1];
 | |
|             if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(text))
 | |
|             {
 | |
|                 Debug.LogWarning($"bad line in csv: {line}");
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             _dict[key] = text.Replace( "\\n", "\n" ); 
 | |
|             count++;
 | |
|         }
 | |
| 
 | |
|         Debug.Log($":: imported {count} lines of dialogue");
 | |
|     }
 | |
| 
 | |
|     private static readonly Dictionary<string, string> _dict = new Dictionary<string, string>();
 | |
| 
 | |
|     public static string[] Keys => _dict.Keys.ToArray();
 | |
| 
 | |
|     public static string ReadDialogue(string key)
 | |
|     {
 | |
|         return _dict.ContainsKey(key)
 | |
|             ? _dict[key]
 | |
|             : $"<color=\"red\">MISSING[{key}]</color>";
 | |
|     }
 | |
| } |