//go:build notmuch // +build notmuch package notmuch /* #cgo LDFLAGS: -lnotmuch #include #include */ import "C" import ( "time" "unsafe" ) type Message struct { message *C.notmuch_message_t } // Close frees resources associated with the message func (m *Message) Close() { C.notmuch_message_destroy(m.message) } // ID returns the message ID func (m *Message) ID() string { cID := C.notmuch_message_get_message_id(m.message) return C.GoString(cID) } // ThreadID returns the thread ID of the message func (m *Message) ThreadID() string { cID := C.notmuch_message_get_thread_id(m.message) return C.GoString(cID) } func (m *Message) Replies() Messages { cMessages := C.notmuch_message_get_replies(m.message) return Messages{ messages: cMessages, } } func (m *Message) TotalFiles() int { return int(C.notmuch_message_count_files(m.message)) } // Filename returns a single filename associated with the message. If the // message has multiple filenames, the return value will be arbitrarily chosen func (m *Message) Filename() string { cFilename := C.notmuch_message_get_filename(m.message) return C.GoString(cFilename) } func (m *Message) Filenames() []string { cFilenames := C.notmuch_message_get_filenames(m.message) defer C.notmuch_filenames_destroy(cFilenames) filenames := []string{} for C.notmuch_filenames_valid(cFilenames) > 0 { filename := C.notmuch_filenames_get(cFilenames) filenames = append(filenames, C.GoString(filename)) C.notmuch_filenames_move_to_next(cFilenames) } return filenames } // TODO is this needed? // func (m *Message) Reindex() error { // // } type Flag int const ( MESSAGE_FLAG_MATCH Flag = iota MESSAGE_FLAG_EXCLUDED MESSAGE_FLAG_GHOST ) func (m *Message) Flag(flag Flag) (bool, error) { var ok C.notmuch_bool_t cFlag := C.notmuch_message_flag_t(flag) err := errorWrap(C.notmuch_message_get_flag_st(m.message, cFlag, &ok)) if err != nil { return false, err } if ok == 0 { return false, nil } return true, nil } // TODO why does this exist?? // func (m *Message) SetFlag(flag Flag) { // // } func (m *Message) Date() time.Time { cTime := C.notmuch_message_get_date(m.message) return time.Unix(int64(cTime), 0) } func (m *Message) Header(field string) string { cField := C.CString(field) defer C.free(unsafe.Pointer(cField)) cHeader := C.notmuch_message_get_header(m.message, cField) return C.GoString(cHeader) } func (m *Message) Tags() []string { cTags := C.notmuch_message_get_tags(m.message) defer C.notmuch_tags_destroy(cTags) tags := []string{} for C.notmuch_tags_valid(cTags) > 0 { tag := C.notmuch_tags_get(cTags) tags = append(tags, C.GoString(tag)) C.notmuch_tags_move_to_next(cTags) } return tags } func (m *Message) AddTag(tag string) error { cTag := C.CString(tag) defer C.free(unsafe.Pointer(cTag)) return errorWrap(C.notmuch_message_add_tag(m.message, cTag)) } func (m *Message) RemoveTag(tag string) error { cTag := C.CString(tag) defer C.free(unsafe.Pointer(cTag)) return errorWrap(C.notmuch_message_remove_tag(m.message, cTag)) } func (m *Message) RemoveAllTags() error { return errorWrap(C.notmuch_message_remove_all_tags(m.message)) } // SyncTagsToMaildirFlags adds/removes the appropriate tags to the maildir // filename func (m *Message) SyncTagsToMaildirFlags() error { return errorWrap(C.notmuch_message_tags_to_maildir_flags(m.message)) } // SyncMaildirFlagsToTags syncs the current maildir flags to the notmuch tags func (m *Message) SyncMaildirFlagsToTags() error { return errorWrap(C.notmuch_message_maildir_flags_to_tags(m.message)) } func (m *Message) HasMaildirFlag(flag rune) (bool, error) { var ok C.notmuch_bool_t err := errorWrap(C.notmuch_message_has_maildir_flag_st(m.message, C.char(flag), &ok)) if err != nil { return false, err } if ok == 0 { return false, nil } return true, nil } func (m *Message) Freeze() error { return errorWrap(C.notmuch_message_freeze(m.message)) } func (m *Message) Thaw() error { return errorWrap(C.notmuch_message_thaw(m.message)) } func (m *Message) Property(key string) (string, error) { var ( cKey *C.char cValue *C.char ) defer C.free(unsafe.Pointer(cKey)) defer C.free(unsafe.Pointer(cValue)) cKey = C.CString(key) err := errorWrap(C.notmuch_message_get_property(m.message, cKey, &cValue)) //nolint:gocritic // see note in notmuch.go if err != nil { return "", err } return C.GoString(cValue), nil } func (m *Message) AddProperty(key string, value string) error { var ( cKey *C.char cValue *C.char ) defer C.free(unsafe.Pointer(cKey)) defer C.free(unsafe.Pointer(cValue)) cKey = C.CString(key) cValue = C.CString(value) return errorWrap(C.notmuch_message_add_property(m.message, cKey, cValue)) } func (m *Message) RemoveProperty(key string, value string) error { var ( cKey *C.char cValue *C.char ) defer C.free(unsafe.Pointer(cKey)) defer C.free(unsafe.Pointer(cValue)) cKey = C.CString(key) cValue = C.CString(value) return errorWrap(C.notmuch_message_remove_property(m.message, cKey, cValue)) } func (m *Message) RemoveAllProperties(key string) error { var cKey *C.char defer C.free(unsafe.Pointer(cKey)) cKey = C.CString(key) return errorWrap(C.notmuch_message_remove_all_properties(m.message, cKey)) } func (m *Message) RemoveAllPropertiesWithPrefix(prefix string) error { var cPrefix *C.char defer C.free(unsafe.Pointer(cPrefix)) cPrefix = C.CString(prefix) return errorWrap(C.notmuch_message_remove_all_properties_with_prefix(m.message, cPrefix)) } func (m *Message) Properties(key string, exact bool) *Properties { var ( cKey *C.char cExact C.int ) defer C.free(unsafe.Pointer(cKey)) if exact { cExact = 1 } cKey = C.CString(key) props := C.notmuch_message_get_properties(m.message, cKey, cExact) return &Properties{ properties: props, } } func (m *Message) CountProperties(key string) (int, error) { var ( cKey *C.char cCount C.uint ) defer C.free(unsafe.Pointer(cKey)) cKey = C.CString(key) err := errorWrap(C.notmuch_message_count_properties(m.message, cKey, &cCount)) if err != nil { return 0, err } return int(cCount), nil }