Сегодня решил немного перекурить документацию по Google Celendar API и доделать работу с событиями календаря, а именно: добавить методы редактирования и удаления события.
На самом деле, что при редактировании, что при удалении практически любого элемента entry в Google Data используется в целом один и тот же универсальный алгоритм, состоящий из трех шагов:
1. Определить значение атрибута (или узла, или заголовка) e-tag
2. Определить ссылку для редактирования (то есть пройтись по узлам link в фиде и вытащить ту, что содержит атрибут rel=»edit»)
3. Сформировать запрос и отправить его методом PUT (для редактирования) или DELETE (для удаления) записи.
В свое время я не поленился и создал необходимые типы данных для всех возможных элементов в XML календаря, включая некоторые из Google Data API. В итоге, например, узел, который 100% является текстовым описывается так:
type TTextTag = class private FName: string; FValue: string; FAttributes: TList; public Constructor Create(const ByNode: IXMLNode); procedure ParseXML(Node: IXMLNode); function AddToXML(Root: IXMLNode): IXMLNode; property Value: string read FValue write FValue; property Name: string read FName write FName; property Attributes: TListread FAttributes write FAttributes; end;
При этом в метод Create передается непосредственно ссылка на узел в документе и все поля класса заполняются данными на этапе создания. Если же на этапе создания узел в документе не определен, то впоследствии можно использовать метод ParseXML для заполнения полей класса. После этого данные можно читать, редактировать. Если узел необходимо вставить в документ, то вызывается метод AddToXML у которого единственный параметр — родительский узел для нового узла.
Может пример класса представлен не совсем удачно, но с помощью этого примера будет разобраться, что я буду делать при работе с событиями Google Celendar. Кстати, начал писать про календарь и вспомнил о настройках Windows 7 — гаджеты, обои для рабочего стола и т.д. Есть там гаджет «Календарь»…Интересно, можно к нему прикрутить Google Celendar? :) Посмотрим потом, когда более-менее разберемся с API, а пока я буду делать следующее — изменять данные в мероприятии. Каждое мероприятие я определяю как класс:
type TCelenrarEvent = class private Fid: string; FEtag: string; FAuth: string; Fpublished: TDateTime; Fupdated: TDateTime; FTitle: TTextTag; FDescription: TTextTag; FLinks: TCelendarLinksList; // ссылки события [...] public constructor Create(const ByNode: IXMLNode; aAuth: string); property Etag: string read FEtag; property PublishedTime: TDateTime read Fpublished; property UpdateTime: TDateTime read Fupdated; property title: TTextTag read FTitle write FTitle; [...] end;
Соответственно для обновления мероприятия в календаре нам необходимо изменить содержимое полей класса и отправить изменения на сервер. Пишем метод Update:
procedure TCelenrarEvent.Update; var i: integer; aDoc: IXMLDocument; Root, Node: IXMLNode; tmpURL: string; begin aDoc := NewXMLDocument(); aDoc.Active := true; Root := aDoc.AddChild('entry'); //добавляем пространства имен for i := 0 to High(clNameSpaces) do Root.DeclareNamespace(clNameSpaces[i, 0], clNameSpaces[i, 1]); //определяем etag мероприятия Root.Attributes['gd:etag'] := FEtag; InsertCategory(Root); Node := aDoc.CreateElement('id', clNameSpaces[0, 1]); Node.Text := Fid; aDoc.DocumentElement.ChildNodes.Add(Node); //записываем узлы в документ FTitle.AddToXML(Root); [...] if length(GetEditURL) > 0 then //если ссылка на редактирование обнаружена в фиде with THTTPSend.Create do begin Headers.Add('GData-Version: 2'); Headers.Add('Authorization: GoogleLogin auth=' + FAuth); MimeType := 'application/atom+xml'; Headers.Add('If-Match: ' + FEtag); aDoc.SaveToStream(Document); HTTPMethod('PUT', GetEditURL); if (ResultCode > 200) and (ResultCode < 400) then begin tmpURL := GetNewLocationURL(Headers); Document.Clear; aDoc.SaveToStream(Document); Headers.Clear; MimeType := 'application/atom+xml'; Headers.Add('GData-Version: 2'); Headers.Add('Authorization: GoogleLogin auth=' + FAuth); Headers.Add('If-Match: ' + FEtag); //не забываем про заголовок! HTTPMethod('PUT', tmpURL); end; end; end;
Вот примерно так можно описать метод для обновления мероприятия. Теперь можно загрузить весь список мероприятий календаря, выбрать то, которое необходимо изменить, изменить необходимые поля в классе и отправить изменения на сервер, используя метод Update. Соответственно, если изменить метод отправки данных с PUT на DELETE и не отправлять никакие данные в документе, за исключением etag, то можно удалить мероприятие из календаря.
Теперь осталось собрать все, что сделано для Google Celendar API в Delphi и либо соорудить компонент, либо небольшую библиотеку для работы с календарями.
Очень интересно. А можно как то прикрутиться к задачам в календаре?
Вполне возможно, что в будущем API календаря доработают в этом плане. Пока к задачам прикрутить ничего нельзя, т.к. календарь «Задачи» устанавливается в режим «Только чтение»
Решил все-таки имя изменить :)))
Нет ли идеи у вас создать единный компонент для работы с google& Готов помочь в реализации
Вообще-то такая мысль была — создать если не компонент, то библиотеку для работы с API Google. Но чем дальше забираюсь в своих познаниях апи гугла, тем больше убеждаюсь, что работы там невпроворот, да и познаний в Delphi не так много как хотелось бы. Поэтому пока собираю из апи то, что необходимо мне в работе. Думаю, что часть того, что сделано для Celendar API выложу где-нибудь на Code.Google. Только вначале исходники в более-менее презентабильный вид приведу :)
А можно ли как-то по API восстановить удаленное событие?
Удалить его получается двумя способами: через отправку DELETE и через изменения eventStatus на «http://schemas.google.com/g/2005#event.canceled». А вот восстановить никак не получается.