// // Copyright 2011 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // using System; using System.Text; using System.Collections; using Google.GData.Apps; using Google.GData.Client; using Google.GData.Calendar; using Google.GData.Extensions; using Google.GData.Extensions.Apps; namespace BookThemAll { public class NoAvailableSlotWithinLimitException : Exception { } public class BookThemAllSample { protected AppsService apps; protected CalendarService calendar; protected static string feedUrl = "https://www.google.com/calendar/feeds/{0}/private/full"; private string admin; public BookThemAllSample(string domain, string admin, string password) { apps = new AppsService(domain, admin, password); calendar = new CalendarService("BookThemAll"); calendar.setUserCredentials(admin, password); this.admin = admin; } public AtomEntryCollection RetrieveAllGroupMembers(string group) { return apps.Groups.RetrieveAllMembers(group).Entries; } public bool IsUserAvailable(string user, DateTime datetime) { EventQuery query = new EventQuery(string.Format(feedUrl, user)); query.StartTime = datetime; query.EndTime = datetime + new System.TimeSpan(0, 0, 30, 0); EventFeed feed = calendar.Query(query); return feed.Entries.Count == 0; } public bool AreUsersAvailable(AtomEntryCollection users, DateTime datetime) { foreach (AppsExtendedEntry entry in users) { string user = entry.getPropertyValueByName("memberId"); bool isAvailable = IsUserAvailable(user, datetime); if (!isAvailable) { return false; } } return true; } public DateTime FindNextAvailableTimeSlot(AtomEntryCollection users, DateTime limit) { DateTime nextHour = NextHour(); while (nextHour < limit) { if (AreUsersAvailable(users, nextHour)) { return nextHour; } nextHour += new System.TimeSpan(0, 0, 30, 0); } throw new NoAvailableSlotWithinLimitException(); } public DateTime NextHour() { DateTime now = DateTime.Now; return now + new System.TimeSpan(0, 0, 59-now.Minute, 59-now.Second, 1000-now.Millisecond); } public EventEntry CreateEvent(string title, DateTime date, AtomEntryCollection users) { EventEntry entry = new EventEntry(); entry.Title.Text = title; entry.Content.Content = title + "Content"; When eventTime = new When(date, date + new System.TimeSpan(0, 0, 30, 0)); entry.Times.Add(eventTime); foreach (AppsExtendedEntry user in users) { string member = user.getPropertyValueByName("memberId"); Who who = new Who(); who.Email = member; who.Rel = Who.RelType.EVENT_ATTENDEE; entry.Participants.Add(who); } Uri postUri = new Uri(string.Format(feedUrl, admin)); return calendar.Insert(postUri, entry); } public DateTime Run(string group) { DateTime now = DateTime.Now; AtomEntryCollection users = RetrieveAllGroupMembers(group); DateTime nextSlot = FindNextAvailableTimeSlot(users, now + new System.TimeSpan(30, 0, 0, 0)); CreateEvent("Meeting", nextSlot, users); return nextSlot; } static void Main(string[] args) { if (args.Length != 4) { Console.WriteLine("Usage: BookThemAll "); } else { // Workaround Certificate validation errors System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { return true; }; string domain = args[0]; string admin = args[1]; string password = args[2]; string group = args[3]; BookThemAllSample bookthemall = new BookThemAllSample(domain, admin, password); Console.WriteLine("Event created at: {0}", bookthemall.Run(group)); } } } }