A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 780 lines 21 kB view raw
1// SiYuan - Refactor your thinking 2// Copyright (c) 2020-present, b3log.org 3// 4// This program is free software: you can redistribute it and/or modify 5// it under the terms of the GNU Affero General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// This program is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU Affero General Public License for more details. 13// 14// You should have received a copy of the GNU Affero General Public License 15// along with this program. If not, see <https://www.gnu.org/licenses/>. 16 17package model 18 19import ( 20 "bytes" 21 "context" 22 "errors" 23 "github.com/siyuan-note/siyuan/kernel/util" 24 "os" 25 "path" 26 "strings" 27 "sync" 28 29 "github.com/88250/gulu" 30 "github.com/emersion/go-ical" 31 "github.com/emersion/go-webdav/caldav" 32 "github.com/siyuan-note/logging" 33) 34 35const ( 36 // REF: https://developers.google.com/calendar/caldav/v2/guide 37 CalDavPrefixPath = "/caldav" 38 CalDavPrincipalsPath = CalDavPrefixPath + "/principals" // 0 resourceTypeRoot 39 CalDavUserPrincipalPath = CalDavPrincipalsPath + "/main" // 1 resourceTypeUserPrincipal 40 CalDavHomeSetPath = CalDavUserPrincipalPath + "/calendars" // 2 resourceTypeCalendarHomeSet 41 CalDavDefaultCalendarPath = CalDavHomeSetPath + "/default" // 3 resourceTypeCalendar 42 43 CalDavDefaultCalendarName = "default" 44 45 CalDavCalendarsMetaDataFilePath = CalDavHomeSetPath + "/calendars.json" 46 47 ICalendarFileExt = "." + ical.Extension // .ics 48) 49 50type CalDavPathDepth int 51 52const ( 53 calDavPathDepth_Root CalDavPathDepth = 1 + iota // /caldav 54 calDavPathDepth_Principals // /caldav/principals 55 calDavPathDepth_UserPrincipal // /caldav/principals/main 56 calDavPathDepth_HomeSet // /caldav/principals/main/calendars 57 calDavPathDepth_Calendar // /caldav/principals/main/calendars/default 58 calDavPathDepth_Object // /caldav/principals/main/calendars/default/id.ics 59) 60 61var ( 62 calendarMaxResourceSize int64 = 0 63 calendarSupportedComponentSet = []string{"VEVENT", "VTODO"} 64 65 defaultCalendar = caldav.Calendar{ 66 Path: CalDavDefaultCalendarPath, 67 Name: CalDavDefaultCalendarName, 68 Description: "Default calendar", 69 MaxResourceSize: calendarMaxResourceSize, 70 SupportedComponentSet: calendarSupportedComponentSet, 71 } 72 calendars = Calendars{ 73 loaded: false, 74 changed: false, 75 lock: sync.Mutex{}, 76 calendars: sync.Map{}, 77 calendarsMetaData: []*caldav.Calendar{}, 78 } 79 80 ErrorCalDavPathInvalid = errors.New("CalDAV: path is invalid") 81 82 ErrorCalDavCalendarNotFound = errors.New("CalDAV: calendar not found") 83 ErrorCalDavCalendarPathInvalid = errors.New("CalDAV: calendar path is invalid") 84 85 ErrorCalDavCalendarObjectNotFound = errors.New("CalDAV: calendar object not found") 86 ErrorCalDavCalendarObjectPathInvalid = errors.New("CalDAV: calendar object path is invalid") 87) 88 89// CalendarsMetaDataFilePath returns the absolute path of the calendars' meta data file 90func CalendarsMetaDataFilePath() string { 91 return DavPath2DirectoryPath(CalDavCalendarsMetaDataFilePath) 92} 93 94func GetCalDavPathDepth(urlPath string) CalDavPathDepth { 95 urlPath = PathCleanWithSlash(urlPath) 96 return CalDavPathDepth(len(strings.Split(urlPath, "/")) - 1) 97} 98 99// GetCardDavPathDepth parses 100func ParseCalendarObjectPath(objectPath string) (calendarPath string, objectID string, err error) { 101 calendarPath, objectFileName := path.Split(objectPath) 102 calendarPath = PathCleanWithSlash(calendarPath) 103 objectID = path.Base(objectFileName) 104 objectFileExt := util.Ext(objectFileName) 105 106 if GetCalDavPathDepth(calendarPath) != calDavPathDepth_Calendar { 107 err = ErrorCalDavCalendarPathInvalid 108 return 109 } 110 111 if objectFileExt != ICalendarFileExt { 112 err = ErrorCalDavCalendarObjectPathInvalid 113 return 114 } 115 116 return 117} 118 119// LoadCalendarObject loads a iCalendar file (*.ics) 120func LoadCalendarObject(filePath string) (calendar *ical.Calendar, err error) { 121 data, err := os.ReadFile(filePath) 122 if err != nil { 123 logging.LogErrorf("read iCalendar file [%s] failed: %s", filePath, err) 124 return 125 } 126 127 decoder := ical.NewDecoder(bytes.NewReader(data)) 128 calendar, err = decoder.Decode() 129 return 130} 131 132type Calendars struct { 133 loaded bool 134 changed bool 135 lock sync.Mutex // load & save 136 calendars sync.Map // Path -> *Calendar 137 calendarsMetaData []*caldav.Calendar 138} 139 140func (c *Calendars) load() error { 141 c.calendars.Clear() 142 143 // load calendars meta data file 144 calendarsMetaDataFilePath := CalendarsMetaDataFilePath() 145 metaData, err := os.ReadFile(calendarsMetaDataFilePath) 146 if os.IsNotExist(err) { 147 // create & save default calendar 148 c.calendarsMetaData = []*caldav.Calendar{&defaultCalendar} 149 if err := c.saveCalendarsMetaData(); err != nil { 150 return err 151 } 152 } else { 153 // load meta data file 154 c.calendarsMetaData = []*caldav.Calendar{} 155 if err = gulu.JSON.UnmarshalJSON(metaData, &c.calendarsMetaData); err != nil { 156 logging.LogErrorf("unmarshal address books meta data failed: %s", err) 157 return err 158 } 159 } 160 161 // load iCalendar files (*.ics) 162 wg := &sync.WaitGroup{} 163 wg.Add(len(c.calendarsMetaData)) 164 for _, calendarMetaData := range c.calendarsMetaData { 165 calendar := &Calendar{ 166 Changed: false, 167 DirectoryPath: DavPath2DirectoryPath(calendarMetaData.Path), 168 MetaData: calendarMetaData, 169 Objects: sync.Map{}, 170 } 171 c.calendars.Store(calendarMetaData.Path, calendar) 172 go func() { 173 defer wg.Done() 174 calendar.load() 175 }() 176 } 177 wg.Wait() 178 179 c.loaded = true 180 c.changed = false 181 return nil 182} 183 184// save all calendars 185func (c *Calendars) save(force bool) error { 186 if force || c.changed { 187 // save calendars meta data 188 if err := c.saveCalendarsMetaData(); err != nil { 189 return err 190 } 191 192 // save all calendar object to *.ics files 193 wg := &sync.WaitGroup{} 194 c.calendars.Range(func(path any, calendar any) bool { 195 wg.Add(1) 196 go func() { 197 defer wg.Done() 198 // path_ := path.(string) 199 calendar := calendar.(*Calendar) 200 calendar.save(force) 201 }() 202 return true 203 }) 204 wg.Wait() 205 c.changed = false 206 } 207 return nil 208} 209 210// save all calendars meta data 211func (c *Calendars) saveCalendarsMetaData() error { 212 return SaveMetaData(c.calendarsMetaData, CalendarsMetaDataFilePath()) 213} 214 215func (c *Calendars) Load() error { 216 c.lock.Lock() 217 defer c.lock.Unlock() 218 219 if !c.loaded { 220 return c.load() 221 } 222 return nil 223} 224 225func (c *Calendars) GetObject(objectPath string) (calendar *Calendar, calendarObject *CalendarObject, err error) { 226 calendarPath, objectID, err := ParseCalendarObjectPath(objectPath) 227 if err != nil { 228 logging.LogErrorf("parse calendar object path [%s] failed: %s", objectPath, err) 229 return 230 } 231 232 if value, ok := c.calendars.Load(calendarPath); ok { 233 calendar = value.(*Calendar) 234 } else { 235 err = ErrorCalDavCalendarNotFound 236 return 237 } 238 239 if value, ok := calendar.Objects.Load(objectID); ok { 240 calendarObject = value.(*CalendarObject) 241 } else { 242 err = ErrorCalDavCalendarObjectNotFound 243 return 244 } 245 246 return 247} 248 249func (c *Calendars) DeleteObject(objectPath string) (calendar *Calendar, calendarObject *CalendarObject, err error) { 250 calendarPath, objectID, err := ParseCalendarObjectPath(objectPath) 251 if err != nil { 252 logging.LogErrorf("parse calendar object path [%s] failed: %s", objectPath, err) 253 return 254 } 255 256 if value, ok := c.calendars.Load(calendarPath); ok { 257 calendar = value.(*Calendar) 258 } else { 259 err = ErrorCalDavCalendarNotFound 260 return 261 } 262 263 if value, loaded := calendar.Objects.LoadAndDelete(objectID); loaded { 264 calendarObject = value.(*CalendarObject) 265 } else { 266 err = ErrorCalDavCalendarObjectNotFound 267 return 268 } 269 270 if err = os.Remove(calendarObject.FilePath); err != nil { 271 logging.LogErrorf("remove file [%s] failed: %s", calendarObject.FilePath, err) 272 return 273 } 274 275 return 276} 277 278func (c *Calendars) CreateCalendar(calendarMetaData *caldav.Calendar) (err error) { 279 c.lock.Lock() 280 defer c.lock.Unlock() 281 282 var calendar *Calendar 283 284 // update map 285 if value, ok := c.calendars.Load(calendarMetaData.Path); ok { 286 // update map item 287 calendar = value.(*Calendar) 288 calendar.MetaData = calendarMetaData 289 } else { 290 // insert map item 291 calendar = &Calendar{ 292 Changed: false, 293 DirectoryPath: DavPath2DirectoryPath(calendarMetaData.Path), 294 MetaData: calendarMetaData, 295 Objects: sync.Map{}, 296 } 297 c.calendars.Store(calendarMetaData.Path, calendar) 298 } 299 300 var index = -1 301 for i, item := range c.calendarsMetaData { 302 if item.Path == calendarMetaData.Path { 303 index = i 304 break 305 } 306 } 307 308 if index >= 0 { 309 // update list 310 c.calendarsMetaData[index] = calendarMetaData 311 } else { 312 // insert list 313 c.calendarsMetaData = append(c.calendarsMetaData, calendarMetaData) 314 } 315 316 // create calendar directory 317 if err = os.MkdirAll(calendar.DirectoryPath, 0755); err != nil { 318 logging.LogErrorf("create directory [%s] failed: %s", calendar.DirectoryPath, err) 319 return 320 } 321 322 // save meta data 323 if err = c.saveCalendarsMetaData(); err != nil { 324 return 325 } 326 327 return 328} 329 330func (c *Calendars) ListCalendars() (calendars []caldav.Calendar, err error) { 331 c.lock.Lock() 332 defer c.lock.Unlock() 333 334 for _, calendar := range c.calendarsMetaData { 335 calendars = append(calendars, *calendar) 336 } 337 return 338} 339 340func (c *Calendars) GetCalendar(calendarPath string) (calendar *caldav.Calendar, err error) { 341 c.lock.Lock() 342 defer c.lock.Unlock() 343 344 if value, ok := calendars.calendars.Load(calendarPath); ok { 345 calendar = value.(*Calendar).MetaData 346 return 347 } 348 349 err = ErrorCalDavCalendarNotFound 350 return 351} 352 353func (c *Calendars) DeleteCalendar(calendarPath string) (err error) { 354 c.lock.Lock() 355 defer c.lock.Unlock() 356 357 var calendar *Calendar 358 359 // delete map item 360 if value, loaded := c.calendars.LoadAndDelete(calendarPath); loaded { 361 calendar = value.(*Calendar) 362 } 363 364 // delete list item 365 for i, item := range c.calendarsMetaData { 366 if item.Path == calendarPath { 367 c.calendarsMetaData = append(c.calendarsMetaData[:i], c.calendarsMetaData[i+1:]...) 368 break 369 } 370 } 371 372 // remove address book directory 373 if err = os.RemoveAll(calendar.DirectoryPath); err != nil { 374 logging.LogErrorf("remove directory [%s] failed: %s", calendar.DirectoryPath, err) 375 return 376 } 377 378 // save meta data 379 if err = c.saveCalendarsMetaData(); err != nil { 380 return 381 } 382 383 return nil 384} 385 386func (c *Calendars) PutCalendarObject(objectPath string, calendarData *ical.Calendar, opts *caldav.PutCalendarObjectOptions) (calendarObject *caldav.CalendarObject, err error) { 387 c.lock.Lock() 388 defer c.lock.Unlock() 389 390 calendarPath, objectID, err := ParseCalendarObjectPath(objectPath) 391 if err != nil { 392 logging.LogErrorf("parse calendar object path [%s] failed: %s", objectPath, err) 393 return 394 } 395 396 var calendar *Calendar 397 if value, ok := c.calendars.Load(calendarPath); ok { 398 calendar = value.(*Calendar) 399 } else { 400 err = ErrorCalDavCalendarNotFound 401 return 402 } 403 404 // TODO: 处理 opts.IfNoneMatch (If-None-Match) 与 opts.IfMatch (If-Match) 405 406 var object *CalendarObject 407 if value, ok := calendar.Objects.Load(objectID); ok { 408 object = value.(*CalendarObject) 409 object.Data.Data = calendarData 410 object.Changed = true 411 } else { 412 object = &CalendarObject{ 413 Changed: true, 414 FilePath: DavPath2DirectoryPath(objectPath), 415 CalendarPath: calendarPath, 416 Data: &caldav.CalendarObject{ 417 Data: calendarData, 418 }, 419 } 420 } 421 422 err = object.save(true) 423 if err != nil { 424 return 425 } 426 427 err = object.update() 428 if err != nil { 429 return 430 } 431 432 calendar.Objects.Store(objectID, object) 433 calendarObject = object.Data 434 return 435} 436 437func (c *Calendars) ListCalendarObjects(calendarPath string, req *caldav.CalendarCompRequest) (calendarObjects []caldav.CalendarObject, err error) { 438 c.lock.Lock() 439 defer c.lock.Unlock() 440 441 var calendar *Calendar 442 if value, ok := c.calendars.Load(calendarPath); ok { 443 calendar = value.(*Calendar) 444 } else { 445 err = ErrorCalDavCalendarNotFound 446 return 447 } 448 449 calendar.Objects.Range(func(id any, object any) bool { 450 // TODO: filter calendar objects' props and comps 451 calendarObjects = append(calendarObjects, *object.(*CalendarObject).Data) 452 return true 453 }) 454 455 return 456} 457 458func (c *Calendars) GetCalendarObject(objectPath string, req *caldav.CalendarCompRequest) (calendarObject *caldav.CalendarObject, err error) { 459 c.lock.Lock() 460 defer c.lock.Unlock() 461 462 _, object, err := c.GetObject(objectPath) 463 if err != nil { 464 return 465 } 466 467 calendarObject = object.Data 468 // TODO: filter calendar object's props and comps 469 return 470} 471 472func (c *Calendars) QueryCalendarObjects(calendarPath string, query *caldav.CalendarQuery) (calendarObjects []caldav.CalendarObject, err error) { 473 c.lock.Lock() 474 defer c.lock.Unlock() 475 476 calendarObjects, err = c.ListCalendarObjects(calendarPath, &query.CompRequest) 477 if err != nil { 478 return 479 } 480 481 calendarObjects, err = caldav.Filter(query, calendarObjects) 482 if err != nil { 483 return 484 } 485 486 return 487} 488 489func (c *Calendars) DeleteCalendarObject(objectPath string) (err error) { 490 c.lock.Lock() 491 defer c.lock.Unlock() 492 493 _, _, err = c.DeleteObject(objectPath) 494 if err != nil { 495 return 496 } 497 498 return 499} 500 501type Calendar struct { 502 Changed bool 503 DirectoryPath string 504 MetaData *caldav.Calendar 505 Objects sync.Map // id -> *CalendarObject 506} 507 508func (c *Calendar) load() error { 509 if err := os.MkdirAll(c.DirectoryPath, 0755); err != nil { 510 logging.LogErrorf("create directory [%s] failed: %s", c.DirectoryPath, err) 511 return err 512 } 513 514 entries, err := os.ReadDir(c.DirectoryPath) 515 if err != nil { 516 logging.LogErrorf("read dir [%s] failed: %s", c.DirectoryPath, err) 517 return err 518 } 519 520 wg := &sync.WaitGroup{} 521 for _, entry := range entries { 522 if !entry.IsDir() { 523 filename := entry.Name() 524 ext := util.Ext(filename) 525 if ext == ICalendarFileExt { 526 wg.Add(1) 527 go func() { 528 defer wg.Done() 529 530 // create & load calendar object 531 calendarObjectFilePath := path.Join(c.DirectoryPath, filename) 532 calendarObject := &CalendarObject{ 533 Changed: false, 534 FilePath: calendarObjectFilePath, 535 CalendarPath: c.MetaData.Path, 536 } 537 err = calendarObject.load() 538 if err != nil { 539 return 540 } 541 542 id := path.Base(filename) 543 c.Objects.Store(id, calendarObject) 544 }() 545 } 546 } 547 } 548 wg.Wait() 549 return nil 550} 551 552// save an calendar to multiple *.ics files 553func (c *Calendar) save(force bool) error { 554 if force || c.Changed { 555 // create directory 556 if err := os.MkdirAll(c.DirectoryPath, 0755); err != nil { 557 logging.LogErrorf("create directory [%s] failed: %s", c.DirectoryPath, err) 558 return err 559 } 560 561 wg := &sync.WaitGroup{} 562 c.Objects.Range(func(id any, object any) bool { 563 wg.Add(1) 564 go func() { 565 defer wg.Done() 566 // id_ := id.(string) 567 object_ := object.(*CalendarObject) 568 object_.save(force) 569 object_.update() 570 }() 571 return true 572 }) 573 wg.Wait() 574 c.Changed = false 575 } 576 577 return nil 578} 579 580type CalendarObject struct { 581 Changed bool 582 FilePath string 583 CalendarPath string 584 Data *caldav.CalendarObject 585} 586 587func (o *CalendarObject) load() error { 588 // load iCalendar file 589 calendarObjectData, err := LoadCalendarObject(o.FilePath) 590 if err != nil { 591 return err 592 } 593 594 // create address object 595 o.Data = &caldav.CalendarObject{ 596 Data: calendarObjectData, 597 } 598 599 // update file info 600 err = o.update() 601 if err != nil { 602 return err 603 } 604 605 o.Changed = false 606 return nil 607} 608 609// save an object to *.ics file 610func (o *CalendarObject) save(force bool) error { 611 if force || o.Changed { 612 var objectData bytes.Buffer 613 614 // encode data 615 encoder := ical.NewEncoder(&objectData) 616 if err := encoder.Encode(o.Data.Data); err != nil { 617 logging.LogErrorf("encode iCalendar [%s] failed: %s", o.Data.Path, err) 618 return err 619 } 620 621 // create directory 622 dirPath := path.Dir(o.FilePath) 623 if err := os.MkdirAll(dirPath, 0755); err != nil { 624 logging.LogErrorf("create directory [%s] failed: %s", dirPath, err) 625 return err 626 } 627 628 // write file 629 if err := os.WriteFile(o.FilePath, objectData.Bytes(), 0755); err != nil { 630 logging.LogErrorf("write file [%s] failed: %s", o.FilePath, err) 631 return err 632 } 633 634 o.Changed = false 635 } 636 return nil 637} 638 639// update file info 640func (o *CalendarObject) update() error { 641 addressFileInfo, err := os.Stat(o.FilePath) 642 if err != nil { 643 logging.LogErrorf("get file [%s] info failed: %s", o.FilePath, err) 644 return err 645 } 646 647 o.Data.Path = PathJoinWithSlash(o.CalendarPath, addressFileInfo.Name()) 648 o.Data.ModTime = addressFileInfo.ModTime() 649 o.Data.ContentLength = addressFileInfo.Size() 650 o.Data.ETag = FileETag(addressFileInfo) 651 652 return nil 653} 654 655type CalDavBackend struct{} 656 657func (b *CalDavBackend) CurrentUserPrincipal(ctx context.Context) (string, error) { 658 // logging.LogDebugf("CalDAV CurrentUserPrincipal") 659 return CalDavUserPrincipalPath, nil 660} 661 662func (b *CalDavBackend) CalendarHomeSetPath(ctx context.Context) (string, error) { 663 // logging.LogDebugf("CalDAV CalendarHomeSetPath") 664 return CalDavHomeSetPath, nil 665} 666 667func (b *CalDavBackend) CreateCalendar(ctx context.Context, calendar *caldav.Calendar) (err error) { 668 // logging.LogDebugf("CalDAV CreateCalendar -> calendar: %#v", calendar) 669 calendar.Path = PathCleanWithSlash(calendar.Path) 670 671 if err = calendars.Load(); err != nil { 672 return 673 } 674 675 err = calendars.CreateCalendar(calendar) 676 // logging.LogDebugf("CalDAV CreateCalendar <- err: %s", err) 677 return 678} 679 680func (b *CalDavBackend) ListCalendars(ctx context.Context) (calendars_ []caldav.Calendar, err error) { 681 // logging.LogDebugf("CalDAV ListCalendars") 682 if err = calendars.Load(); err != nil { 683 return 684 } 685 686 calendars_, err = calendars.ListCalendars() 687 // logging.LogDebugf("CalDAV ListCalendars <- calendars: %#v, err: %s", calendars_, err) 688 return 689} 690 691func (b *CalDavBackend) GetCalendar(ctx context.Context, calendarPath string) (calendar *caldav.Calendar, err error) { 692 // logging.LogDebugf("CalDAV GetCalendar -> calendarPath: %s", calendarPath) 693 calendarPath = PathCleanWithSlash(calendarPath) 694 695 if err = calendars.Load(); err != nil { 696 return 697 } 698 699 calendar, err = calendars.GetCalendar(calendarPath) 700 // logging.LogDebugf("CalDAV GetCalendar <- calendar: %#v, err: %s", calendar, err) 701 return 702} 703 704func (b *CalDavBackend) DeleteCalendar(ctx context.Context, calendarPath string) (err error) { 705 // logging.LogDebugf("CalDAV DeleteCalendar -> calendarPath: %s", calendarPath) 706 calendarPath = PathCleanWithSlash(calendarPath) 707 708 if err = calendars.Load(); err != nil { 709 return 710 } 711 712 err = calendars.DeleteCalendar(calendarPath) 713 // logging.LogDebugf("CalDAV DeleteCalendar <- err: %s", err) 714 return 715} 716 717func (b *CalDavBackend) PutCalendarObject(ctx context.Context, objectPath string, calendar *ical.Calendar, opts *caldav.PutCalendarObjectOptions) (calendarObject *caldav.CalendarObject, err error) { 718 // logging.LogDebugf("CalDAV PutCalendarObject -> objectPath: %s, opts: %#v", objectPath, opts) 719 objectPath = PathCleanWithSlash(objectPath) 720 721 if err = calendars.Load(); err != nil { 722 return 723 } 724 725 calendarObject, err = calendars.PutCalendarObject(objectPath, calendar, opts) 726 // logging.LogDebugf("CalDAV PutCalendarObject <- calendarObject: %#v, err: %s", calendarObject, err) 727 return 728} 729 730func (b *CalDavBackend) ListCalendarObjects(ctx context.Context, calendarPath string, req *caldav.CalendarCompRequest) (calendarObjects []caldav.CalendarObject, err error) { 731 // logging.LogDebugf("CalDAV ListCalendarObjects -> calendarPath: %s, req: %#v", calendarPath, req) 732 calendarPath = PathCleanWithSlash(calendarPath) 733 734 if err = calendars.Load(); err != nil { 735 return 736 } 737 738 calendarObjects, err = calendars.ListCalendarObjects(calendarPath, req) 739 // logging.LogDebugf("CalDAV ListCalendarObjects <- calendarObjects: %#v, err: %s", calendarObjects, err) 740 return 741} 742 743func (b *CalDavBackend) GetCalendarObject(ctx context.Context, objectPath string, req *caldav.CalendarCompRequest) (calendarObject *caldav.CalendarObject, err error) { 744 // logging.LogDebugf("CalDAV GetCalendarObject -> objectPath: %s, req: %#v", objectPath, req) 745 objectPath = PathCleanWithSlash(objectPath) 746 747 if err = calendars.Load(); err != nil { 748 return 749 } 750 751 calendarObject, err = calendars.GetCalendarObject(objectPath, req) 752 // logging.LogDebugf("CalDAV GetCalendarObject <- calendarObject: %#v, err: %s", calendarObject, err) 753 return 754} 755 756func (b *CalDavBackend) QueryCalendarObjects(ctx context.Context, calendarPath string, query *caldav.CalendarQuery) (calendarObjects []caldav.CalendarObject, err error) { 757 // logging.LogDebugf("CalDAV QueryCalendarObjects -> calendarPath: %s, query: %#v", calendarPath, query) 758 calendarPath = PathCleanWithSlash(calendarPath) 759 760 if err = calendars.Load(); err != nil { 761 return 762 } 763 764 calendarObjects, err = calendars.QueryCalendarObjects(calendarPath, query) 765 // logging.LogDebugf("CalDAV QueryCalendarObjects <- calendarObjects: %#v, err: %s", calendarObjects, err) 766 return 767} 768 769func (b *CalDavBackend) DeleteCalendarObject(ctx context.Context, objectPath string) (err error) { 770 // logging.LogDebugf("CalDAV DeleteCalendarObject -> objectPath: %s", objectPath) 771 objectPath = PathCleanWithSlash(objectPath) 772 773 if err = calendars.Load(); err != nil { 774 return 775 } 776 777 err = calendars.DeleteCalendarObject(objectPath) 778 // logging.LogDebugf("CalDAV DeleteCalendarObject <- err: %s", err) 779 return 780}