Add project files.
This commit is contained in:
358
GoogleAPI.cs
Normal file
358
GoogleAPI.cs
Normal file
@@ -0,0 +1,358 @@
|
||||
using Google.Apis.Auth.OAuth2;
|
||||
using Google.Apis.Gmail.v1;
|
||||
using Google.Apis.Services;
|
||||
using Google.Apis.Sheets.v4;
|
||||
using Google.Apis.Sheets.v4.Data;
|
||||
using Google.Apis.Util.Store;
|
||||
using System.Net.Mail;
|
||||
using System.Net.Mime;
|
||||
using System.Reflection;
|
||||
|
||||
namespace AiQ_GUI
|
||||
{
|
||||
internal class GoogleAPI
|
||||
{
|
||||
public static UserCredential credential;
|
||||
public static SheetsService service = new();
|
||||
const string ApplicationName = "Google Sheets API .NET Quickstart";
|
||||
static readonly string credPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
|
||||
public const string spreadsheetId_ModelInfo = "1bCcCr4OYqfjmydt6UqtmN4FQETezXmZRSStJdCCcqZM";
|
||||
public const string DrivePath = @"G:\Shared drives\MAV Production GUI's\"; // Path to google shared drive
|
||||
|
||||
// Startup and make necessary connections to Google servers and make sure user is logged in
|
||||
public static bool Setup()
|
||||
{
|
||||
try
|
||||
{
|
||||
string streamPath = $"{DrivePath}R50IQ\\client_secret.json";
|
||||
string[] Scopes = [SheetsService.Scope.Spreadsheets];
|
||||
FileStream stream = new(streamPath, FileMode.Open, FileAccess.Read);
|
||||
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.FromStream(stream).Secrets, Scopes, "user", CancellationToken.None, new FileDataStore(credPath, true)).Result;
|
||||
service = new SheetsService(new BaseClientService.Initializer()
|
||||
{
|
||||
HttpClientInitializer = credential,
|
||||
ApplicationName = ApplicationName,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Write a 1D array range to a spreadsheet
|
||||
public static void WriteToSS(List<object> ToWrite, string Range, string SSID)
|
||||
{
|
||||
ValueRange ValueRange = new() { Values = [ToWrite] };
|
||||
SpreadsheetsResource.ValuesResource.UpdateRequest Update = service.Spreadsheets.Values.Update(ValueRange, SSID, Range);
|
||||
Update.ValueInputOption = SpreadsheetsResource.ValuesResource.UpdateRequest.ValueInputOptionEnum.RAW;
|
||||
Update.Execute();
|
||||
}
|
||||
|
||||
// Read a range from a spreadsheet, always returns a 2D object even if 1D is requested
|
||||
public static IList<IList<object>> ReadSS(string sheet, string Location)
|
||||
{
|
||||
return service.Spreadsheets.Values.Get(sheet, Location).Execute().Values;
|
||||
}
|
||||
|
||||
// Checks the WIP columns of a given serial number
|
||||
public static bool CheckWIP(string SerialNumber, string spreadsheetId)
|
||||
{
|
||||
int Row = CheckSerialNumRow(spreadsheetId, SerialNumber); // Get row of serial number - 1 because don't want next row in this case
|
||||
IList<IList<object>> valuesRow = ReadSS(spreadsheetId, $"S{Row}"); // Check if that row is WIP or not
|
||||
return Convert.ToBoolean(valuesRow[0][0]);
|
||||
}
|
||||
|
||||
// Update serial number register with relevant details about the camera that has passed
|
||||
public static string UpdateSpreadSheetPreTest(string spreadsheetId, Versions Vers, string CamDesc, string ModelOnTest)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Finds next row to be used by length of returned array and add 1
|
||||
IList<IList<object>> values = service.Spreadsheets.Values.Get(spreadsheetId, "B1:B").Execute().Values;
|
||||
int nextRow = values != null ? values.Count + 1 : 0;
|
||||
|
||||
if (values?.Count > 0)
|
||||
{
|
||||
// Serial number location = nextRow - 2 (Array starts at 0 but spreadsheet starts at 1 & next row has already added one so need to get rid)
|
||||
string lastSerialNumber = Convert.ToString(values[nextRow - 2][0]);
|
||||
int NewSerialNumberInt = Convert.ToInt32(lastSerialNumber.Substring(1)) + 1; // Generate new serial number knowing the last
|
||||
string newSerialNumber = "K" + NewSerialNumberInt.ToString();
|
||||
|
||||
// Send data to spreadsheet and set WIP to TRUE
|
||||
List<object> oblistAE = // Write columns A-E
|
||||
[
|
||||
ModelOnTest,
|
||||
newSerialNumber,
|
||||
CamDesc,
|
||||
"Pre Test: " + DateTime.Now.ToString("dd/MM/yyyy"),
|
||||
Vers.version + " - " + Vers.revision + Environment.NewLine + Vers.buildtime + Environment.NewLine + Vers.proquint,
|
||||
];
|
||||
WriteToSS(oblistAE, $"A{nextRow}:E{nextRow}", spreadsheetId);
|
||||
|
||||
// Write MAC to column H
|
||||
List<object> oblistH = [Vers.MAC];
|
||||
WriteToSS(oblistH, $"H{nextRow}", spreadsheetId);
|
||||
|
||||
List<object> oblistN = [$"GUI Version: {GUIUpdate.GUIVerShort}"]; // Write column N
|
||||
WriteToSS(oblistN, $"N{nextRow}", spreadsheetId);
|
||||
|
||||
// Write TRUE to WIP checkbox in column S
|
||||
List<object> oblistS = ["TRUE"];
|
||||
WriteToSS(oblistS, $"S{nextRow}", spreadsheetId);
|
||||
|
||||
return newSerialNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Last serial number not found";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return $"ERROR: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
// Update serial number register with relevant details about the camera that has passed
|
||||
public static string UpdateSpreadSheetRePreTest(string spreadsheetId, Versions Vers)
|
||||
{
|
||||
try
|
||||
{
|
||||
int CamRow = CheckSerialNumRow(spreadsheetId, Vers.Serial);
|
||||
|
||||
if (CamRow != 0)
|
||||
{
|
||||
// Send data to spreadsheet and set WIP to TRUE
|
||||
List<object> oblistDE = // Write columns D-E
|
||||
[
|
||||
"Pre Test: " + DateTime.Now.ToString("dd/MM/yyyy"),
|
||||
Vers.version + " - " + Vers.revision + Environment.NewLine + Vers.buildtime + Environment.NewLine + Vers.proquint,
|
||||
];
|
||||
WriteToSS(oblistDE, $"D{CamRow}:E{CamRow}", spreadsheetId);
|
||||
|
||||
// Write MAC to column H
|
||||
List<object> oblistH = [Vers.MAC];
|
||||
WriteToSS(oblistH, $"H{CamRow}", spreadsheetId);
|
||||
|
||||
List<object> oblistN = [$"GUI Version: {GUIUpdate.GUIVerShort}"]; // Write column N
|
||||
WriteToSS(oblistN, $"N{CamRow}", spreadsheetId);
|
||||
|
||||
// Write TRUE to WIP checkbox in column S
|
||||
List<object> oblistS = ["TRUE"];
|
||||
WriteToSS(oblistS, $"S{CamRow}", spreadsheetId);
|
||||
|
||||
return "OK";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Serial number not found";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return $"ERROR: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
// Update serial number register with relevant details about the camera that has passed
|
||||
public static string UpdateSpreadSheetFinalTest(string spreadsheetId, Diags DiagsAPI, SSHData sshData, int RMANum)
|
||||
{
|
||||
try
|
||||
{
|
||||
int CamRow = CheckSerialNumRow(spreadsheetId, DiagsAPI.serialNumber);
|
||||
|
||||
IList<IList<object>> valuesRow = ReadSS(spreadsheetId, $"D{CamRow}");
|
||||
string TestDate = Convert.ToString(valuesRow[0][0]) + Environment.NewLine + "Final Test: " + DateTime.Now.ToString("dd/MM/yyyy");
|
||||
|
||||
if (RMANum != 0)
|
||||
TestDate = TestDate.Replace("Final", "RMA"); // So it will say RMA Test in the spreadsheet.
|
||||
|
||||
// Write column D
|
||||
List<object> oblistD = [TestDate];
|
||||
WriteToSS(oblistD, $"D{CamRow}", spreadsheetId);
|
||||
|
||||
List<object> oblistFG = // Write columns F-G
|
||||
[
|
||||
DiagsAPI.licenses.raptorKeyID,
|
||||
sshData.packages
|
||||
];
|
||||
WriteToSS(oblistFG, $"F{CamRow}:G{CamRow}", spreadsheetId);
|
||||
|
||||
List<object> oblistNR = // Write columns N-S
|
||||
[
|
||||
$"GUI Version: {GUIUpdate.GUIVerShort}",
|
||||
DiagsAPI.licenses.saf1,
|
||||
DiagsAPI.licenses.audit,
|
||||
DiagsAPI.licenses.stream,
|
||||
sshData.tailscale,
|
||||
"FALSE" // Write FALSE to WIP checkbox in column S
|
||||
];
|
||||
WriteToSS(oblistNR, $"N{CamRow}:S{CamRow}", spreadsheetId);
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return "Failed to update spreadsheet data, please check manually" + ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
// Update Vaxtor spreadsheet
|
||||
public static string UpdateSpreadSheetVaxtor(VaxtorLic VaxtorLicResp, string serial, string model)
|
||||
{
|
||||
try
|
||||
{
|
||||
string spreadsheetId = "1n5zhmI4Tz6JFr0stLNFOR6GsxGEKBEhrVKQ6yncM-LA";
|
||||
int nextRow = CheckNextFree(spreadsheetId);
|
||||
|
||||
List<object> oblistCF = // Write columns C-F
|
||||
[
|
||||
model,
|
||||
serial,
|
||||
DateTime.Now.ToString("dd/MM/yyyy"),
|
||||
VaxtorLicResp.protectionKeyId,
|
||||
];
|
||||
WriteToSS(oblistCF, $"C{nextRow}:F{nextRow}", spreadsheetId);
|
||||
|
||||
// Write PROD to column H
|
||||
List<object> oblistH = ["PROD"];
|
||||
WriteToSS(oblistH, $"H{nextRow}", spreadsheetId);
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return "Failed to update spreadsheet data, please check manually" + ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
// Checks RMA control sheet for a model and serial that match current camera
|
||||
public static int CheckRMANum(string serial, string model)
|
||||
{
|
||||
string spreadsheetId_RMAControl = "1tZhkYrqBQ3BcL7ZS4q3ghzCgHSJ8f5LVSj7nh6fIRC8";
|
||||
try
|
||||
{
|
||||
// Get all info in H and I columns
|
||||
IList<IList<object>> valuesRMA = service.Spreadsheets.Values.Get(spreadsheetId_RMAControl, "H2:I").Execute().Values;
|
||||
|
||||
for (int i = 0; i < valuesRMA.Count; i++)
|
||||
{
|
||||
try // In case line is blank
|
||||
{
|
||||
// Checks is serial and model num in RMA control spreadsheet match what is in the camera
|
||||
if (valuesRMA[i][0].ToString().Contains(serial) && valuesRMA[i][1].ToString().Contains(model))
|
||||
{
|
||||
int OnRow = i + 2; // Offset for start of the sheet and starting at 1
|
||||
valuesRMA = service.Spreadsheets.Values.Get(spreadsheetId_RMAControl, "A" + OnRow).Execute().Values;
|
||||
return Convert.ToInt16(valuesRMA[0][0]); // Once it has found the serial it gusses at the RMA number
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return 0; // If it can't be found
|
||||
}
|
||||
|
||||
// Checks RMA control sheet for a model and serial that match current camera
|
||||
public static int CheckSerialNumRow(string spreadsheetId, string serial)
|
||||
{
|
||||
// Get all info in B column
|
||||
IList<IList<object>> valuesRMA = service.Spreadsheets.Values.Get(spreadsheetId, "B:B").Execute().Values;
|
||||
|
||||
for (int i = 0; i < valuesRMA.Count; i++)
|
||||
{
|
||||
try // In case line is blank
|
||||
{
|
||||
// Checks is serial and model num in RMA control spreadsheet match what is in the camera
|
||||
if (valuesRMA[i][0].ToString().Contains(serial))
|
||||
{
|
||||
return i + 1; // Offset for sheet starting at 1
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
return 0; // If it can't be found
|
||||
}
|
||||
|
||||
// Checks Vaxtor sheet for next free row
|
||||
public static int CheckNextFree(string spreadsheetId)
|
||||
{
|
||||
IList<IList<object>> valuesRMA = service.Spreadsheets.Values.Get(spreadsheetId, "C2:C").Execute().Values; // Get how many C cows
|
||||
return valuesRMA.Count + 2; // Gets the amount of rows, offsets for start from 1 error and adds one to be next row
|
||||
}
|
||||
|
||||
public static void EmailApproval(string ApprovalRow, string User)
|
||||
{
|
||||
FileStream GmailStream = new($"{DrivePath}R50IQ\\creds.json", FileMode.Open, FileAccess.Read);
|
||||
string[] ScopesGmail = [GmailService.Scope.GmailSend];
|
||||
|
||||
using (GmailStream)
|
||||
{
|
||||
string credPathGmail = Path.Combine(credPath, ".credentials/gmail-dotnet-quickstart.json");
|
||||
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.FromStream(GmailStream).Secrets, ScopesGmail, "user", CancellationToken.None, new FileDataStore(credPathGmail, true)).Result;
|
||||
GmailStream.Close();
|
||||
}
|
||||
|
||||
// Build the MIME message with attachment
|
||||
using MailMessage mail = new MailMessage();
|
||||
mail.From = new MailAddress("me");
|
||||
mail.To.Add("richard.porter@mav-systems.com");
|
||||
mail.To.Add("bradley.relyea@mav-systems.com");
|
||||
mail.To.Add("bradley.born@mav-systems.com");
|
||||
mail.Subject = "Approval required";
|
||||
mail.Body = $"Dear Rich,<br><br>Camera needs approval<br>" +
|
||||
$"https://docs.google.com/spreadsheets/d/1bCcCr4OYqfjmydt6UqtmN4FQETezXmZRSStJdCCcqZM/edit#gid=1931079354&range=A{ApprovalRow}" +
|
||||
$"<br><br><br>Thanks,<br><br>{User}";
|
||||
mail.IsBodyHtml = true;
|
||||
|
||||
// Attach the log file if it exists
|
||||
string logFilePath = LDS.MAVPath + Logging.LogFileName;
|
||||
if (File.Exists(logFilePath))
|
||||
{
|
||||
Attachment logAttachment = new(logFilePath, MediaTypeNames.Text.Plain);
|
||||
logAttachment.Name = Logging.LogFileName;
|
||||
mail.Attachments.Add(logAttachment);
|
||||
}
|
||||
|
||||
// Save the MIME message to a stream
|
||||
using MemoryStream ms = new();
|
||||
SmtpClient smtpClient = new(); // Only used to access the internal Write method
|
||||
Type mailWriterType = typeof(SmtpClient).Assembly.GetType("System.Net.Mail.MailWriter");
|
||||
object? mailWriter = Activator.CreateInstance(
|
||||
mailWriterType,
|
||||
BindingFlags.Instance | BindingFlags.NonPublic,
|
||||
null,
|
||||
[ms, true],
|
||||
null);
|
||||
|
||||
typeof(MailMessage).InvokeMember(
|
||||
"Send",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
|
||||
null,
|
||||
mail,
|
||||
[mailWriter, true, true]);
|
||||
|
||||
ms.Position = 0;
|
||||
byte[] rawBytes = ms.ToArray();
|
||||
|
||||
GmailService service = new(new BaseClientService.Initializer()
|
||||
{
|
||||
HttpClientInitializer = credential,
|
||||
ApplicationName = ApplicationName,
|
||||
});
|
||||
|
||||
Google.Apis.Gmail.v1.Data.Message newMsg = new()
|
||||
{
|
||||
Raw = Convert.ToBase64String(rawBytes)
|
||||
.Replace("+", "-")
|
||||
.Replace("/", "_")
|
||||
.Replace("=", "")
|
||||
};
|
||||
|
||||
service.Users.Messages.Send(newMsg, "me").Execute();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user