1
0
mirror of https://github.com/dstotijn/go-notion.git synced 2024-11-28 08:58:51 +02:00
go-notion/database.go

523 lines
18 KiB
Go

package notion
import (
"encoding/json"
"errors"
"time"
)
// Database is a resource on the Notion platform.
// See: https://developers.notion.com/reference/database
type Database struct {
ID string `json:"id"`
CreatedTime time.Time `json:"created_time"`
CreatedBy BaseUser `json:"created_by"`
LastEditedTime time.Time `json:"last_edited_time"`
LastEditedBy BaseUser `json:"last_edited_by"`
URL string `json:"url"`
Title []RichText `json:"title"`
Properties DatabaseProperties `json:"properties"`
Parent Parent `json:"parent"`
Icon *Icon `json:"icon,omitempty"`
Cover *Cover `json:"cover,omitempty"`
Archived bool `json:"archived"`
}
// DatabaseProperties is a mapping of properties defined on a database.
type DatabaseProperties map[string]DatabaseProperty
// Database property metadata types.
type (
EmptyMetadata struct{}
NumberMetadata struct {
Format NumberFormat `json:"format"`
}
SelectMetadata struct {
Options []SelectOptions `json:"options"`
}
FormulaMetadata struct {
Expression string `json:"expression"`
}
RelationMetadata struct {
DatabaseID string `json:"database_id,omitempty"`
SyncedPropName string `json:"synced_property_name,omitempty"`
SyncedPropID string `json:"synced_property_id,omitempty"`
}
RollupMetadata struct {
RelationPropName string `json:"relation_property_name,omitempty"`
RelationPropID string `json:"relation_property_id,omitempty"`
RollupPropName string `json:"rollup_property_name,omitempty"`
RollupPropID string `json:"rollup_property_id,omitempty"`
Function RollupFunction `json:"function,omitempty"`
}
)
type RollupFunction string
const (
RollupFunctionCountAll RollupFunction = "count_all"
RollupFunctionCountValues RollupFunction = "count_values"
RollupFunctionCountUniqueValues RollupFunction = "count_unique_values"
RollupFunctionCountEmpty RollupFunction = "count_empty"
RollupFunctionCountNotEmpty RollupFunction = "count_not_empty"
RollupFunctionPercentEmpty RollupFunction = "percent_empty"
RollupFunctionPercentNotEmpty RollupFunction = "percent_not_empty"
RollupFunctionSum RollupFunction = "sum"
RollupFunctionAverage RollupFunction = "average"
RollupFunctionMedian RollupFunction = "median"
RollupFunctionMin RollupFunction = "min"
RollupFunctionMax RollupFunction = "max"
RollupFunctionRange RollupFunction = "range"
RollupFunctionShowOriginal RollupFunction = "show_original"
)
type SelectOptions struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Color Color `json:"color,omitempty"`
}
type FormulaResult struct {
Type FormulaResultType `json:"type"`
String *string `json:"string,omitempty"`
Number *float64 `json:"number,omitempty"`
Boolean *bool `json:"boolean,omitempty"`
Date *Date `json:"date,omitempty"`
}
type Relation struct {
ID string `json:"id"`
}
type RollupResult struct {
Type RollupResultType `json:"type"`
Number *float64 `json:"number,omitempty"`
Date *Date `json:"date,omitempty"`
Array []DatabasePageProperty `json:"array,omitempty"`
}
type People struct {
People []User `json:"people"`
}
type File struct {
Name string `json:"name"`
Type FileType `json:"type"`
File *FileFile `json:"file,omitempty"`
External *FileExternal `json:"external,omitempty"`
}
type DatabaseProperty struct {
ID string `json:"id,omitempty"`
Type DatabasePropertyType `json:"type"`
Name string `json:"name,omitempty"`
Title *EmptyMetadata `json:"title,omitempty"`
RichText *EmptyMetadata `json:"rich_text,omitempty"`
Date *EmptyMetadata `json:"date,omitempty"`
People *EmptyMetadata `json:"people,omitempty"`
Files *EmptyMetadata `json:"files,omitempty"`
Checkbox *EmptyMetadata `json:"checkbox,omitempty"`
URL *EmptyMetadata `json:"url,omitempty"`
Email *EmptyMetadata `json:"email,omitempty"`
PhoneNumber *EmptyMetadata `json:"phone_number,omitempty"`
CreatedTime *EmptyMetadata `json:"created_time,omitempty"`
CreatedBy *EmptyMetadata `json:"created_by,omitempty"`
LastEditedTime *EmptyMetadata `json:"last_edited_time,omitempty"`
LastEditedBy *EmptyMetadata `json:"last_edited_by,omitempty"`
Number *NumberMetadata `json:"number,omitempty"`
Select *SelectMetadata `json:"select,omitempty"`
MultiSelect *SelectMetadata `json:"multi_select,omitempty"`
Formula *FormulaMetadata `json:"formula,omitempty"`
Relation *RelationMetadata `json:"relation,omitempty"`
Rollup *RollupMetadata `json:"rollup,omitempty"`
}
// DatabaseQuery is used for quering a database.
type DatabaseQuery struct {
Filter *DatabaseQueryFilter `json:"filter,omitempty"`
Sorts []DatabaseQuerySort `json:"sorts,omitempty"`
StartCursor string `json:"start_cursor,omitempty"`
PageSize int `json:"page_size,omitempty"`
}
// DatabaseQueryResponse contains the results and pagination data from a query request.
type DatabaseQueryResponse struct {
Results []Page `json:"results"`
HasMore bool `json:"has_more"`
NextCursor *string `json:"next_cursor"`
}
// DatabaseQueryFilter is used to filter database contents.
// See: https://developers.notion.com/reference/post-database-query#post-database-query-filter
type DatabaseQueryFilter struct {
Property string `json:"property,omitempty"`
DatabaseQueryPropertyFilter
Timestamp Timestamp `json:"timestamp,omitempty"`
Or []DatabaseQueryFilter `json:"or,omitempty"`
And []DatabaseQueryFilter `json:"and,omitempty"`
}
type DatabaseQueryPropertyFilter struct {
Title *TextPropertyFilter `json:"title,omitempty"`
RichText *TextPropertyFilter `json:"rich_text,omitempty"`
URL *TextPropertyFilter `json:"url,omitempty"`
Email *TextPropertyFilter `json:"email,omitempty"`
PhoneNumber *TextPropertyFilter `json:"phone_number,omitempty"`
Date *DatePropertyFilter `json:"date,omitempty"`
CreatedTime *DatePropertyFilter `json:"created_time,omitempty"`
LastEditedTime *DatePropertyFilter `json:"last_edited_time,omitempty"`
Number *NumberDatabaseQueryFilter `json:"number,omitempty"`
Checkbox *CheckboxDatabaseQueryFilter `json:"checkbox,omitempty"`
Select *SelectDatabaseQueryFilter `json:"select,omitempty"`
MultiSelect *MultiSelectDatabaseQueryFilter `json:"multi_select,omitempty"`
People *PeopleDatabaseQueryFilter `json:"people,omitempty"`
Files *FilesDatabaseQueryFilter `json:"files,omitempty"`
Relation *RelationDatabaseQueryFilter `json:"relation,omitempty"`
Formula *FormulaDatabaseQueryFilter `json:"formula,omitempty"`
Rollup *RollupDatabaseQueryFilter `json:"rollup,omitempty"`
CreatedBy *PeopleDatabaseQueryFilter `json:"created_by,omitempty"`
LastEditedBy *PeopleDatabaseQueryFilter `json:"last_edited_by,omitempty"`
}
type Timestamp string
const (
TimestampCreatedTime = "created_time"
TimestampLastEditedTime = "last_edited_time"
)
type TextPropertyFilter struct {
Equals string `json:"equals,omitempty"`
DoesNotEqual string `json:"does_not_equal,omitempty"`
Contains string `json:"contains,omitempty"`
DoesNotContain string `json:"does_not_contain,omitempty"`
StartsWith string `json:"starts_with,omitempty"`
EndsWith string `json:"ends_with,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}
type NumberDatabaseQueryFilter struct {
Equals *int `json:"equals,omitempty"`
DoesNotEqual *int `json:"does_not_equal,omitempty"`
GreaterThan *int `json:"greater_than,omitempty"`
LessThan *int `json:"less_than,omitempty"`
GreaterThanOrEqualTo *int `json:"greater_than_or_equal_to,omitempty"`
LessThanOrEqualTo *int `json:"less_than_or_equal_to,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}
type CheckboxDatabaseQueryFilter struct {
Equals *bool `json:"equals,omitempty"`
DoesNotEqual *bool `json:"does_not_equal,omitempty"`
}
type SelectDatabaseQueryFilter struct {
Equals string `json:"equals,omitempty"`
DoesNotEqual string `json:"does_not_equal,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}
type MultiSelectDatabaseQueryFilter struct {
Contains string `json:"contains,omitempty"`
DoesNotContain string `json:"does_not_contain,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}
type DatePropertyFilter struct {
Equals *time.Time `json:"equals,omitempty"`
Before *time.Time `json:"before,omitempty"`
After *time.Time `json:"after,omitempty"`
OnOrBefore *time.Time `json:"on_or_before,omitempty"`
OnOrAfter *time.Time `json:"on_or_after,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
PastWeek *struct{} `json:"past_week,omitempty"`
PastMonth *struct{} `json:"past_month,omitempty"`
PastYear *struct{} `json:"past_year,omitempty"`
NextWeek *struct{} `json:"next_week,omitempty"`
NextMonth *struct{} `json:"next_month,omitempty"`
NextYear *struct{} `json:"next_year,omitempty"`
}
type PeopleDatabaseQueryFilter struct {
Contains string `json:"contains,omitempty"`
DoesNotContain string `json:"does_not_contain,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}
type FilesDatabaseQueryFilter struct {
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}
type RelationDatabaseQueryFilter struct {
Contains string `json:"contains,omitempty"`
DoesNotContain string `json:"does_not_contain,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}
type RollupDatabaseQueryFilter struct {
Any *DatabaseQueryPropertyFilter `json:"any,omitempty"`
Every *DatabaseQueryPropertyFilter `json:"every,omitempty"`
None *DatabaseQueryPropertyFilter `json:"none,omitempty"`
Number *NumberDatabaseQueryFilter `json:"number,omitempty"`
Date *DatePropertyFilter `json:"date,omitempty"`
}
type FormulaDatabaseQueryFilter struct {
String *TextPropertyFilter `json:"string,omitempty"`
Checkbox *CheckboxDatabaseQueryFilter `json:"checkbox,omitempty"`
Number *NumberDatabaseQueryFilter `json:"number,omitempty"`
Date *DatePropertyFilter `json:"date,omitempty"`
}
type DatabaseQuerySort struct {
Property string `json:"property,omitempty"`
Timestamp SortTimestamp `json:"timestamp,omitempty"`
Direction SortDirection `json:"direction,omitempty"`
}
// CreateDatabaseParams are the params used for creating a database.
type CreateDatabaseParams struct {
ParentPageID string
Title []RichText
Properties DatabaseProperties
Icon *Icon
Cover *Cover
}
type (
DatabasePropertyType string
NumberFormat string
FormulaResultType string
RollupResultType string
SortTimestamp string
SortDirection string
)
const (
// Database property type enums.
DBPropTypeTitle DatabasePropertyType = "title"
DBPropTypeRichText DatabasePropertyType = "rich_text"
DBPropTypeNumber DatabasePropertyType = "number"
DBPropTypeSelect DatabasePropertyType = "select"
DBPropTypeMultiSelect DatabasePropertyType = "multi_select"
DBPropTypeDate DatabasePropertyType = "date"
DBPropTypePeople DatabasePropertyType = "people"
DBPropTypeFiles DatabasePropertyType = "files"
DBPropTypeCheckbox DatabasePropertyType = "checkbox"
DBPropTypeURL DatabasePropertyType = "url"
DBPropTypeEmail DatabasePropertyType = "email"
DBPropTypePhoneNumber DatabasePropertyType = "phone_number"
DBPropTypeFormula DatabasePropertyType = "formula"
DBPropTypeRelation DatabasePropertyType = "relation"
DBPropTypeRollup DatabasePropertyType = "rollup"
DBPropTypeCreatedTime DatabasePropertyType = "created_time"
DBPropTypeCreatedBy DatabasePropertyType = "created_by"
DBPropTypeLastEditedTime DatabasePropertyType = "last_edited_time"
DBPropTypeLastEditedBy DatabasePropertyType = "last_edited_by"
// Used for paginated property values.
// See: https://developers.notion.com/reference/property-item-object#paginated-property-values
DBPropTypePropertyItem DatabasePropertyType = "property_item"
// Number format enums.
NumberFormatNumber NumberFormat = "number"
NumberFormatNumberWithCommas NumberFormat = "number_with_commas"
NumberFormatPercent NumberFormat = "percent"
NumberFormatDollar NumberFormat = "dollar"
NumberFormatEuro NumberFormat = "euro"
NumberFormatPound NumberFormat = "pound"
NumberFormatPonud NumberFormat = "yen"
NumberFormatRuble NumberFormat = "ruble"
NumberFormatRupee NumberFormat = "rupee"
NumberFormatWon NumberFormat = "won"
NumberFormatYuan NumberFormat = "yuan"
NumberFormatHongKongDollar NumberFormat = "hong_kong_dollar"
NumberFormatNewZealandDollar NumberFormat = "new_zealand_dollar"
NumberFormatKrona NumberFormat = "krona"
NumberFormatNorwegianKrone NumberFormat = "norwegian_krone"
NumberFormatMexicanPeso NumberFormat = "mexican_peso"
NumberFormatRand NumberFormat = "rand"
NumberFormatNewTaiwanDollar NumberFormat = "new_taiwan_dollar"
NumberFormatDanishKrone NumberFormat = "danish_krone"
NumberFormatZloty NumberFormat = "zloty"
NumberFormatBaht NumberFormat = "baht"
NumberFormatForint NumberFormat = "forint"
NumberFormatKoruna NumberFormat = "koruna"
NumberFormatShekel NumberFormat = "shekel"
NumberFormatChileanPeso NumberFormat = "chilean_peso"
NumberFormatPhilippinePeso NumberFormat = "philippine_peso"
NumberFormatDirham NumberFormat = "dirham"
NumberFormatColombianPeso NumberFormat = "colombian_peso"
NumberFormatRiyal NumberFormat = "riyal"
NumberFormatRinggit NumberFormat = "ringgit"
NumberFormatLeu NumberFormat = "leu"
// Formula result type enums.
FormulaResultTypeString FormulaResultType = "string"
FormulaResultTypeNumber FormulaResultType = "number"
FormulaResultTypeBoolean FormulaResultType = "boolean"
FormulaResultTypeDate FormulaResultType = "date"
// Rollup result type enums.
RollupResultTypeNumber RollupResultType = "number"
RollupResultTypeDate RollupResultType = "date"
RollupResultTypeArray RollupResultType = "array"
RollupResultTypeUnsupported RollupResultType = "unsupported"
RollupResultTypeIncomplete RollupResultType = "incomplete"
// Sort timestamp enums.
SortTimeStampCreatedTime SortTimestamp = "created_time"
SortTimeStampLastEditedTime SortTimestamp = "last_edited_time"
// Sort direction enums.
SortDirAsc SortDirection = "ascending"
SortDirDesc SortDirection = "descending"
)
// Metadata returns the underlying property metadata, based on its `type` field.
// When type is unknown/unmapped or doesn't have additional properies, `nil` is returned.
func (prop DatabaseProperty) Metadata() interface{} {
switch prop.Type {
case "title":
return prop.Title
case "number":
return prop.Number
case "select":
return prop.Select
case "multi_select":
return prop.MultiSelect
case "formula":
return prop.Formula
case "relation":
return prop.Relation
case "rollup":
return prop.Rollup
default:
return nil
}
}
// Value returns the underlying result value of an evaluated formula.
func (f FormulaResult) Value() interface{} {
switch f.Type {
case FormulaResultTypeString:
return f.String
case FormulaResultTypeNumber:
return f.Number
case FormulaResultTypeBoolean:
return f.Boolean
case FormulaResultTypeDate:
return f.Date
default:
return nil
}
}
// Value returns the underlying result value of an evaluated rollup.
func (r RollupResult) Value() interface{} {
switch r.Type {
case RollupResultTypeNumber:
return r.Number
case RollupResultTypeDate:
return r.Date
case RollupResultTypeArray:
return r.Array
default:
return nil
}
}
// Validate validates params for creating a database.
func (p CreateDatabaseParams) Validate() error {
if p.ParentPageID == "" {
return errors.New("parent page ID is required")
}
if p.Properties == nil {
return errors.New("database properties are required")
}
if p.Icon != nil {
if err := p.Icon.Validate(); err != nil {
return err
}
}
if p.Cover != nil {
if err := p.Cover.Validate(); err != nil {
return err
}
}
return nil
}
// MarshalJSON implements json.Marshaler.
func (p CreateDatabaseParams) MarshalJSON() ([]byte, error) {
type CreatePageParamsDTO struct {
Parent Parent `json:"parent"`
Title []RichText `json:"title,omitempty"`
Properties DatabaseProperties `json:"properties"`
Icon *Icon `json:"icon,omitempty"`
Cover *Cover `json:"cover,omitempty"`
}
parent := Parent{
Type: ParentTypePage,
PageID: p.ParentPageID,
}
dto := CreatePageParamsDTO{
Parent: parent,
Title: p.Title,
Properties: p.Properties,
Icon: p.Icon,
Cover: p.Cover,
}
return json.Marshal(dto)
}
// UpdateDatabaseParams are the params used for updating a database.
type UpdateDatabaseParams struct {
Title []RichText `json:"title,omitempty"`
Properties map[string]*DatabaseProperty `json:"properties,omitempty"`
Icon *Icon `json:"icon,omitempty"`
Cover *Cover `json:"cover,omitempty"`
Archived *bool `json:"archived,omitempty"`
}
// Validate validates params for updating a database.
func (p UpdateDatabaseParams) Validate() error {
if len(p.Title) == 0 && len(p.Properties) == 0 {
return errors.New("either title or properties are required")
}
if p.Icon != nil {
if err := p.Icon.Validate(); err != nil {
return err
}
}
if p.Cover != nil {
if err := p.Cover.Validate(); err != nil {
return err
}
}
return nil
}