using Google.Apis.Auth.OAuth2;
using Google.Apis.Calendar.v3;
using Google.Apis.Calendar.v3.Data;
using Google.Apis.People.v1;
using Google.Apis.PeopleService.v1.Data;
using Google.Apis.Util.Store;
using NodaTime;
using NUnit.Framework;
using Serilog;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading;
namespace GoContactSyncMod.UnitTests
{
[TestFixture]
public class GoogleAPITests
{
private EventsResource eventsService = null;
private CalendarListEntry primaryCalendar = null;
[OneTimeSetUp]
public void Init()
{
LoadSettings(out var gmailUsername, out _);
var scopes = new List<string>();
//Contacts-Scope
scopes.Add(Google.Apis.People.v1.PeopleService.Scope.Contacts);
//Calendar-Scope
scopes.Add(CalendarService.Scope.Calendar);
UserCredential credential;
var jsonSecrets = Properties.Resources.client_secrets;
using (var stream = new MemoryStream(jsonSecrets))
{
var Folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\GoContactSyncMOD\\";
var AuthFolder = Folder + "\\Auth\\";
var fDS = new FileDataStore(AuthFolder, true);
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets, scopes, gmailUsername, CancellationToken.None,
fDS).Result;
var initializer = new Google.Apis.Services.BaseClientService.Initializer
{
HttpClientInitializer = credential
};
var CalendarRequest = new CalendarService(initializer);
var list = CalendarRequest.CalendarList.List().Execute().Items;
foreach (var calendar in list)
{
if (calendar.Primary != null && calendar.Primary.Value)
{
primaryCalendar = calendar;
break;
}
}
if (primaryCalendar == null)
{
throw new Exception("Primary Calendar not found");
}
eventsService = CalendarRequest.Events;
}
}
[Test]
public void CreateNewPerson()
{
LoadSettings(out var gmailUsername, out _);
PeopleService service;
var scopes = new List<string>();
//Contacts-Scope
scopes.Add(Google.Apis.People.v1.PeopleService.Scope.Contacts);
//Calendar-Scope
scopes.Add(CalendarService.Scope.Calendar);
UserCredential credential;
var jsonSecrets = Properties.Resources.client_secrets;
using (var stream = new MemoryStream(jsonSecrets))
{
var Folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\GoContactSyncMOD\\";
var AuthFolder = Folder + "\\Auth\\";
var fDS = new FileDataStore(AuthFolder, true);
var clientSecrets = GoogleClientSecrets.Load(stream);
credential = GCSMOAuth2WebAuthorizationBroker.AuthorizeAsync(
clientSecrets.Secrets,
scopes.ToArray(),
gmailUsername,
CancellationToken.None,
fDS).
Result;
var initializer = new Google.Apis.Services.BaseClientService.Initializer
{
HttpClientInitializer = credential
};
//var parameters = new OAuth2Parameters
//{
// ClientId = clientSecrets.Secrets.ClientId,
// ClientSecret = clientSecrets.Secrets.ClientSecret,
// // Note: AccessToken is valid only for 60 minutes
// AccessToken = credential.Token.AccessToken,
// RefreshToken = credential.Token.RefreshToken
//};
//var settings = new RequestSettings("GoContactSyncMod", parameters);
service = GoogleServices.CreatePeopleService(initializer);
}
#region Delete previously created test contact.
var peopleResource = new Google.Apis.PeopleService.v1.PeopleResource(service);
var query = peopleResource.Connections.List("people/me");
//{
// NumberToRetrieve = 500;
//};
var feed = query.Execute();
Log.Information("Loaded Google contacts");
foreach (var entry in feed.Connections)
{
var pm = ContactPropertiesUtils.GetGoogleContactPrimaryEmail(entry);
if (pm != null && pm.Value == "johndoe@example.com")
{
peopleResource.CreateContact(entry).Execute();
Log.Information("Deleted Google contact");
//break;
}
}
#endregion
var newEntry = new Person();
var name = ContactPropertiesUtils.GetGoogleContactName(newEntry);
if (name == null)
{
name = new Name();
newEntry.Names.Add(name);
}
name.UnstructuredName = "John Doe";
var primaryEmail = new EmailAddress
{
Value = "johndoe@example.com",
Metadata = new FieldMetadata
{
Primary = true
},
Type = "work"
};
newEntry.EmailAddresses.Add(primaryEmail);
var phoneNumber = new PhoneNumber
{
Value = "555-555-5551",
Metadata = new FieldMetadata
{
Primary = true
},
Type = "mobile"
};
newEntry.PhoneNumbers.Add(phoneNumber);
var address = new Address
{
StreetAddress = "123 somewhere lane",
Metadata = new FieldMetadata
{
Primary = true
},
Type = "home"
};
newEntry.Addresses.Add(address);
newEntry.Biographies.Add(new Biography { Value = "Who is this guy?" });
//var feedUri = new Uri(ContactsQuery.CreateContactsUri("default"));
var createdEntry = peopleResource.CreateContact(newEntry).Execute();
Log.Information("Created Google contact");
Assert.IsNotNull(createdEntry.ResourceName);
_ = peopleResource.UpdateContact(createdEntry, createdEntry.ResourceName).Execute();
Log.Information("Updated Google contact");
//delete test contacts
peopleResource.DeleteContact(createdEntry.ResourceName).Execute();
Log.Information("Deleted Google contact");
}
[Test]
public void CreateNewAppointment()
{
#region Delete previously created test contact.
var query = eventsService.List(primaryCalendar.Id);
query.MaxResults = 500;
query.TimeMin = DateTime.Now.AddDays(-10);
query.TimeMax = DateTime.Now.AddDays(10);
var feed = query.Execute();
Log.Information("Loaded Google appointments");
foreach (var entry in feed.Items)
{
if (entry.Summary != null && entry.Summary.Contains("GCSM Test Appointment") && !entry.Status.Equals("cancelled"))
{
Log.Information("Deleting Google appointment:" + entry.Summary + " - " + entry.Start.DateTime.ToString());
eventsService.Delete(primaryCalendar.Id, entry.Id);
Log.Information("Deleted Google appointment");
//break;
}
}
#endregion
var newEntry = Factory.NewEvent();
newEntry.Summary = "GCSM Test Appointment";
newEntry.Start.DateTime = DateTime.Now;
newEntry.End.DateTime = DateTime.Now;
var createdEntry = eventsService.Insert(newEntry, primaryCalendar.Id).Execute();
Log.Information("Created Google appointment");
Assert.IsNotNull(createdEntry.Id);
var updatedEntry = eventsService.Update(createdEntry, primaryCalendar.Id, createdEntry.Id).Execute();
Log.Information("Updated Google appointment");
//delete test contacts
eventsService.Delete(primaryCalendar.Id, updatedEntry.Id).Execute();
Log.Information("Deleted Google appointment");
}
[Test]
public void Test_OldRecurringAppointment()
{
#region Delete previously created test contact.
var query = eventsService.List(primaryCalendar.Id);
query.MaxResults = 500;
query.TimeMin = DateTime.Now.AddDays(-10);
query.TimeMax = DateTime.Now.AddDays(10);
//query.Q = "GCSM Test Appointment";
var feed = query.Execute();
Log.Information("Loaded Google appointments");
foreach (var entry in feed.Items)
{
if (entry.Summary != null && entry.Summary.Contains("GCSM Test Appointment") && !entry.Status.Equals("cancelled"))
{
Log.Information("Deleting Google appointment:" + entry.Summary + " - " + entry.Start.DateTime.ToString());
eventsService.Delete(primaryCalendar.Id, entry.Id);
Log.Information("Deleted Google appointment");
//break;
}
}
#endregion
var zone = DateTimeZoneProviders.Tzdb["Europe/Warsaw"];
var e1_start = new LocalDateTime(1970, 10, 14, 10, 0, 0);
var e1_start_zoned = e1_start.InZoneLeniently(zone);
var e1_start_utc = e1_start_zoned.ToDateTimeUtc();
_ = new LocalDateTime(1970, 10, 14, 11, 0, 0);
_ = e1_start.InZoneLeniently(zone);
var e1_end_utc = e1_start_zoned.ToDateTimeUtc();
var s = new EventDateTime
{
DateTime = e1_start_utc,
TimeZone = "Europe/Warsaw"
};
var e = new EventDateTime
{
DateTime = e1_end_utc,
TimeZone = "Europe/Warsaw"
};
var e1 = new Google.Apis.Calendar.v3.Data.Event()
{
Summary = "Birthday 1",
Start = s,
End = e,
Recurrence = new string[] { "RRULE:FREQ=YEARLY;BYMONTHDAY=14;BYMONTH=10" }
};
Assert.AreEqual("1970-10-14T09:00:00.000Z", e1.Start.DateTimeRaw);
var c1 = eventsService.Insert(e1, primaryCalendar.Id).Execute();
Assert.AreEqual("1970-10-14T10:00:00+01:00", c1.Start.DateTimeRaw);
var e2_start = new LocalDateTime(2000, 10, 14, 10, 0, 0);
var e2_start_zoned = e2_start.InZoneLeniently(zone);
var e2_start_utc = e2_start_zoned.ToDateTimeUtc();
_ = new LocalDateTime(2000, 10, 14, 11, 0, 0);
_ = e2_start.InZoneLeniently(zone);
var e2_end_utc = e2_start_zoned.ToDateTimeUtc();
var ss = new EventDateTime
{
DateTime = e2_start_utc,
TimeZone = "Europe/Warsaw"
};
var ee = new EventDateTime
{
DateTime = e2_end_utc,
TimeZone = "Europe/Warsaw"
};
var e2 = new Google.Apis.Calendar.v3.Data.Event()
{
Summary = "Birthday 2",
Start = ss,
End = ee,
Recurrence = new string[] { "RRULE:FREQ=YEARLY;BYMONTHDAY=14;BYMONTH=10" }
};
Assert.AreEqual("2000-10-14T08:00:00.000Z", e2.Start.DateTimeRaw);
var c2 = eventsService.Insert(e2, primaryCalendar.Id).Execute();
Assert.AreEqual("2000-10-14T10:00:00+02:00", c2.Start.DateTimeRaw);
Log.Information("Created Google appointment");
Assert.IsNotNull(c1.Id);
//delete test contacts
eventsService.Delete(primaryCalendar.Id, c1.Id).Execute();
eventsService.Delete(primaryCalendar.Id, c2.Id).Execute();
Log.Information("Deleted Google appointment");
}
[Test]
public void Test_RetrieveRecurrenceInstance()
{
var e = new Google.Apis.Calendar.v3.Data.Event()
{
Summary = "AN_OUTLOOK_TEST_APPOINTMENT",
Start = new EventDateTime()
{
DateTime = new DateTime(2020, 6, 3, 15, 0, 0),
TimeZone = "Europe/Warsaw"
},
End = new EventDateTime()
{
DateTime = new DateTime(2020, 6, 3, 16, 0, 0),
TimeZone = "Europe/Warsaw"
},
Recurrence = new string[] { "RRULE:FREQ=WEEKLY;UNTIL=20200625;BYDAY=WE" }
};
e = eventsService.Insert(e, primaryCalendar.Id).Execute();
Assert.IsNotNull(e.Id);
var r = eventsService.Instances(primaryCalendar.Id, e.Id);
var dt = new DateTime(2020, 6, 10, 13, 0, 0, DateTimeKind.Utc);
var s = dt.ToLocalTime().ToString("yyyy-MM-ddTHH:mm:sszzz");
Assert.AreEqual("2020-06-10T15:00:00+02:00", s);
r.OriginalStart = "2020-06-10T15:00:00+02:00";
var instances = r.Execute();
Assert.IsNotNull(instances);
Assert.AreEqual(1, instances.Items.Count);
//delete test contacts
eventsService.Delete(primaryCalendar.Id, e.Id).Execute();
Log.Information("Deleted Google appointment");
}
[Test]
public void CreateContactWithLargeNotes()
{
LoadSettings(out var gmailUsername, out _);
PeopleService service;
var scopes = new List<string>();
//Contacts-Scope
scopes.Add(Google.Apis.People.v1.PeopleService.Scope.Contacts);
//Calendar-Scope
scopes.Add(CalendarService.Scope.Calendar);
UserCredential credential;
var jsonSecrets = Properties.Resources.client_secrets;
using (var stream = new MemoryStream(jsonSecrets))
{
var Folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\GoContactSyncMOD\\";
var AuthFolder = Folder + "\\Auth\\";
var fDS = new FileDataStore(AuthFolder, true);
var clientSecrets = GoogleClientSecrets.Load(stream);
credential = GCSMOAuth2WebAuthorizationBroker.AuthorizeAsync(
clientSecrets.Secrets,
scopes.ToArray(),
gmailUsername,
CancellationToken.None,
fDS).
Result;
var initializer = new Google.Apis.Services.BaseClientService.Initializer
{
HttpClientInitializer = credential
};
/*var parameters = new OAuth2Parameters
{
ClientId = clientSecrets.Secrets.ClientId,
ClientSecret = clientSecrets.Secrets.ClientSecret,
// Note: AccessToken is valid only for 60 minutes
AccessToken = credential.Token.AccessToken,
RefreshToken = credential.Token.RefreshToken
};
var settings = new RequestSettings("GoContactSyncMod", parameters);*/
service = GoogleServices.CreatePeopleService(initializer);
}
#region Delete previously created test contact.
var peopleResource = new Google.Apis.PeopleService.v1.PeopleResource(service);
var query = peopleResource.Connections.List("people/me");
//{
// NumberToRetrieve = 500
//};
var feed = query.Execute();
Log.Information("Loaded Google contacts");
foreach (var entry in feed.Connections)
{
var pm = ContactPropertiesUtils.GetGoogleContactPrimaryEmail(entry);
if (pm != null && pm.Value == "johndoe@example.com")
{
peopleResource.DeleteContact(entry.ResourceName).Execute();
Log.Information("Deleted Google contact");
//break;
}
}
#endregion
var newEntry = new Person();
var name = ContactPropertiesUtils.GetGoogleContactName(newEntry);
if (name == null)
{
name = new Name();
newEntry.Names.Add(name);
}
name.UnstructuredName = "John Doe";
var primaryEmail = new EmailAddress
{
Value = "johndoe@example.com",
Metadata = new FieldMetadata { Primary = true },
Type = "work"
};
newEntry.EmailAddresses.Add(primaryEmail);
var phoneNumber = new PhoneNumber
{
Value = "555-555-5551",
Metadata = new FieldMetadata { Primary = true },
Type = "mobile"
};
newEntry.PhoneNumbers.Add(phoneNumber);
var address = new Address
{
StreetAddress = "123 somewhere lane",
Metadata = new FieldMetadata { Primary = true },
Type = "home"
};
newEntry.Addresses.Add(address);
newEntry.Biographies.Add(new Biography { Value = new string('*', 150000) });
//var feedUri = new Uri(ContactsQuery.CreateContactsUri("default"));
try
{
var createdEntry = peopleResource.CreateContact(newEntry).Execute();
Log.Information("Created Google contact");
Assert.IsNotNull(createdEntry.ResourceName);
_ = peopleResource.UpdateContact(createdEntry, createdEntry.ResourceName).Execute();
Log.Information("Updated Google contact");
//delete test contacts
peopleResource.DeleteContact(createdEntry.ResourceName).Execute();
}
catch (Google.GoogleApiException ex) when (ex.Error != null && ex.Error.ErrorResponseContent.Contains("Request data is too large."))
{
Log.Information(ex,"Exception");
}
Log.Information("Deleted Google contact");
}
internal static void LoadSettings(out string gmailUsername, out string syncProfile, out string syncContactsFolder, out string syncAppointmentsFolder)
{
var regKeyAppRoot = LoadSettings(out gmailUsername, out syncProfile);
syncContactsFolder = "";
syncAppointmentsFolder = "";
Synchronizer.SyncAppointmentsGoogleFolder = "";
//First, check if there is a folder called GCSMTestContacts available, if yes, use them
var outlookContactFolders = new ArrayList();
var outlookAppointmentFolders = new ArrayList();
var folders = Synchronizer.OutlookNameSpace.Folders;
foreach (Microsoft.Office.Interop.Outlook.Folder folder in folders)
{
try
{
SettingsForm.GetOutlookMAPIFolders(outlookContactFolders, outlookAppointmentFolders, folder);
}
catch (Exception e)
{
Log.Warning("Error getting available Outlook folders: " + e.Message);
}
}
foreach (OutlookFolder folder in outlookContactFolders)
{
if (folder.FolderName.ToUpper().Contains("GCSMTestContacts".ToUpper()))
{
Log.Information("Uses Test folder: " + folder.DisplayName);
syncContactsFolder = folder.FolderID;
break;
}
}
foreach (OutlookFolder folder in outlookAppointmentFolders)
{
if (folder.FolderName.ToUpper().Contains("GCSMTestAppointments".ToUpper()))
{
Log.Information("Uses Test folder: " + folder.DisplayName);
syncAppointmentsFolder = folder.FolderID;
break;
}
}
if (string.IsNullOrEmpty(syncContactsFolder))
{
if (regKeyAppRoot.GetValue("SyncContactsFolder") != null)
{
syncContactsFolder = regKeyAppRoot.GetValue("SyncContactsFolder") as string;
}
}
if (string.IsNullOrEmpty(syncAppointmentsFolder))
{
if (regKeyAppRoot.GetValue("SyncAppointmentsFolder") != null)
{
syncAppointmentsFolder = regKeyAppRoot.GetValue("SyncAppointmentsFolder") as string;
}
}
if (string.IsNullOrEmpty(Synchronizer.SyncAppointmentsGoogleFolder))
{
if (regKeyAppRoot.GetValue("SyncAppointmentsGoogleFolder") != null)
{
Synchronizer.SyncAppointmentsGoogleFolder = regKeyAppRoot.GetValue("SyncAppointmentsGoogeFolder") as string;
}
}
}
private static Microsoft.Win32.RegistryKey LoadSettings(out string gmailUsername, out string syncProfile)
{
//sync.LoginToGoogle(ConfigurationManager.AppSettings["Gmail.Username"], ConfigurationManager.AppSettings["Gmail.Password"]);
//ToDo: Reading the username and config from the App.Config file doesn't work. If it works, consider special characters like & = & in the XML file
//ToDo: Maybe add a common Test account to the App.config and read it from there, encrypt the password
//For now, read the userName from the Registry (same settings as for GoogleContactsSync Application
gmailUsername = "";
const string appRootKey = SettingsForm.AppRootKey;
var regKeyAppRoot = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(appRootKey);
syncProfile = "Default Profile";
if (regKeyAppRoot.GetValue("SyncProfile") != null)
{
syncProfile = regKeyAppRoot.GetValue("SyncProfile") as string;
}
regKeyAppRoot = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(appRootKey + (syncProfile != null ? ('\\' + syncProfile) : ""));
if (regKeyAppRoot.GetValue("Username") != null)
{
gmailUsername = regKeyAppRoot.GetValue("Username") as string;
}
return regKeyAppRoot;
}
private void Logger_LogUpdated(string message)
{
Console.WriteLine(message);
}
}
}