Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
8f0ce0900e | |||
d9cddc4371 | |||
7c879a0fca | |||
be482dfe41 | |||
b6f63cf15b |
@ -1,14 +1,14 @@
|
|||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "0.3.1"
|
version = "0.4.3"
|
||||||
author = "Jonathan Bernard"
|
author = "Jonathan Bernard"
|
||||||
description = "Utilities and bindings for HFF's Notion API."
|
description = "Utilities and bindings for HFF's Notion API."
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
srcDir = "src"
|
srcDir = "src"
|
||||||
|
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|
||||||
requires "nim >= 1.4.8"
|
requires "nim >= 1.4.8"
|
||||||
requires "https://git.jdb-software.com/jdb/buffoonery"
|
requires "https://git.jdb-software.com/jdb/buffoonery"
|
||||||
requires "https://git.jdb-software.com/jdb/nim-time-utils.git >= 0.5.0"
|
requires "https://git.jdb-software.com/jdb/nim-time-utils.git >= 0.5.0"
|
||||||
|
requires "https://git.jdb-software.com/jdb/nim-namespaced-logging"
|
||||||
|
@ -76,6 +76,14 @@ proc fetchAllPages*(
|
|||||||
|
|
||||||
if nextCursor.isEmptyOrWhitespace: break
|
if nextCursor.isEmptyOrWhitespace: break
|
||||||
|
|
||||||
|
template fetchDatabaseObject*(notion: NotionClient, dbId: string): untyped =
|
||||||
|
let resp = notion.http.get(notion.apiBaseUrl & "/databases/" & dbId)
|
||||||
|
|
||||||
|
if not resp.status.startsWith("2"):
|
||||||
|
debug resp.body
|
||||||
|
raise newException(HttpRequestError, "API Request failed: " & resp.body)
|
||||||
|
parseJson(resp.body)
|
||||||
|
|
||||||
template fetchPage*(notion: NotionClient, pageId: string): untyped =
|
template fetchPage*(notion: NotionClient, pageId: string): untyped =
|
||||||
let resp = notion.http.get(notion.apiBaseUrl & "/pages/" & pageId)
|
let resp = notion.http.get(notion.apiBaseUrl & "/pages/" & pageId)
|
||||||
|
|
||||||
|
@ -19,8 +19,11 @@ type
|
|||||||
FamilyObj* = object
|
FamilyObj* = object
|
||||||
id*: string
|
id*: string
|
||||||
name*: string
|
name*: string
|
||||||
|
headsOfHousehold*: seq[string]
|
||||||
headOfHouseholdIds*: seq[string]
|
headOfHouseholdIds*: seq[string]
|
||||||
primaryAddressId*: seq[string]
|
primaryAddress*: string
|
||||||
|
primaryAddressId*: string
|
||||||
|
members*: seq[string]
|
||||||
memberIds*: seq[string]
|
memberIds*: seq[string]
|
||||||
createdAt*: Option[DateTime]
|
createdAt*: Option[DateTime]
|
||||||
lastUpdatedAt*: Option[DateTime]
|
lastUpdatedAt*: Option[DateTime]
|
||||||
@ -35,10 +38,14 @@ type
|
|||||||
gender*: string
|
gender*: string
|
||||||
primaryPhoneNumber*: string
|
primaryPhoneNumber*: string
|
||||||
primaryEmailAddress*: string
|
primaryEmailAddress*: string
|
||||||
|
addresses*: seq[string]
|
||||||
addressIds*: seq[string]
|
addressIds*: seq[string]
|
||||||
marriedToId*: seq[string]
|
marriedTo*: string
|
||||||
|
marriedToId*: string
|
||||||
anniversary*: Option[DateTime]
|
anniversary*: Option[DateTime]
|
||||||
|
parents*: seq[string]
|
||||||
parentIds*: seq[string]
|
parentIds*: seq[string]
|
||||||
|
children*: seq[string]
|
||||||
childIds*: seq[string]
|
childIds*: seq[string]
|
||||||
relationshipToHff*: seq[string]
|
relationshipToHff*: seq[string]
|
||||||
createdAt*: Option[DateTime]
|
createdAt*: Option[DateTime]
|
||||||
@ -78,8 +85,8 @@ func sameContents[T](a: seq[T], b: seq[T]): bool =
|
|||||||
func `==`*(a, b: Family): bool =
|
func `==`*(a, b: Family): bool =
|
||||||
return a.name == b.name and
|
return a.name == b.name and
|
||||||
sameContents(a.headOfHouseholdIds, b.headOfHouseholdIds) and
|
sameContents(a.headOfHouseholdIds, b.headOfHouseholdIds) and
|
||||||
sameContents(a.primaryAddressId, b.primaryAddressId) and
|
sameContents(a.memberIds, b.memberIds) and
|
||||||
sameContents(a.memberIds, b.memberIds)
|
a.primaryAddressId == b.primaryAddressId
|
||||||
|
|
||||||
func `==`*(a, b: Person): bool =
|
func `==`*(a, b: Person): bool =
|
||||||
return a.preferredName == b.preferredName and
|
return a.preferredName == b.preferredName and
|
||||||
@ -91,8 +98,8 @@ func `==`*(a, b: Person): bool =
|
|||||||
a.primaryPhoneNumber == b.primaryPhoneNumber and
|
a.primaryPhoneNumber == b.primaryPhoneNumber and
|
||||||
a.primaryEmailAddress == b.primaryEmailAddress and
|
a.primaryEmailAddress == b.primaryEmailAddress and
|
||||||
a.anniversary == b.anniversary and
|
a.anniversary == b.anniversary and
|
||||||
|
a.marriedToId == b.marriedToId and
|
||||||
sameContents(a.addressIds, b.addressIds) and
|
sameContents(a.addressIds, b.addressIds) and
|
||||||
sameContents(a.marriedToId, b.marriedToId) and
|
|
||||||
sameContents(a.parentIds, b.parentIds) and
|
sameContents(a.parentIds, b.parentIds) and
|
||||||
sameContents(a.childIds, b.childIds) and
|
sameContents(a.childIds, b.childIds) and
|
||||||
sameContents(a.relationshipToHff, b.relationshipToHff)
|
sameContents(a.relationshipToHff, b.relationshipToHff)
|
||||||
@ -129,7 +136,7 @@ func toPage*(f: Family): JsonNode =
|
|||||||
"properties": {
|
"properties": {
|
||||||
"Name": makeTextProp("title", f.name),
|
"Name": makeTextProp("title", f.name),
|
||||||
"Head(s) of Household": makeRelationProp(f.headOfHouseholdIds),
|
"Head(s) of Household": makeRelationProp(f.headOfHouseholdIds),
|
||||||
"Primary Address": makeRelationProp(f.primaryAddressId),
|
"Primary Address": makeRelationProp(@[f.primaryAddressId]),
|
||||||
"Members": makeRelationProp(f.memberIds)
|
"Members": makeRelationProp(f.memberIds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,7 +154,7 @@ func toPage*(p: Person): JsonNode =
|
|||||||
"Email Address": { "email": p.primaryEmailAddress },
|
"Email Address": { "email": p.primaryEmailAddress },
|
||||||
"Relationship to HFF": makeMultiSelectProp(p.relationshipToHff),
|
"Relationship to HFF": makeMultiSelectProp(p.relationshipToHff),
|
||||||
"Address": makeRelationProp(p.addressIds),
|
"Address": makeRelationProp(p.addressIds),
|
||||||
"Married To": makeRelationProp(p.marriedToId),
|
"Married To": makeRelationProp(@[p.marriedToId]),
|
||||||
"Anniversary": makeDateProp(p.anniversary),
|
"Anniversary": makeDateProp(p.anniversary),
|
||||||
"Parents": makeRelationProp(p.parentIds),
|
"Parents": makeRelationProp(p.parentIds),
|
||||||
"Children": makeRelationProp(p.childIds),
|
"Children": makeRelationProp(p.childIds),
|
||||||
@ -180,16 +187,24 @@ proc addressFromPage*(page: JsonNode): Address =
|
|||||||
lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)))
|
lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)))
|
||||||
|
|
||||||
proc familyFromPage*(page: JsonNode): Family =
|
proc familyFromPage*(page: JsonNode): Family =
|
||||||
|
let primaryAddressIds = page.getRelationIds("Primary Address")
|
||||||
result = Family(
|
result = Family(
|
||||||
id: page["id"].getStr,
|
id: page["id"].getStr,
|
||||||
name: page.getTitle("Name"),
|
name: page.getTitle("Name"),
|
||||||
|
headsOfHousehold: page.getRolledupRecordTitles("Head(s) of Household (display)"),
|
||||||
headOfHouseholdIds: page.getRelationIds("Head(s) of Household"),
|
headOfHouseholdIds: page.getRelationIds("Head(s) of Household"),
|
||||||
primaryAddressId: page.getRelationIds("Primary Address"),
|
primaryAddress: if primaryAddressIds.len == 0: ""
|
||||||
|
else: page.getRolledupRecordTitles("Primary Address (display)")[0],
|
||||||
|
primaryAddressId: if primaryAddressIds.len == 0: ""
|
||||||
|
else: primaryAddressIds[0],
|
||||||
|
members: page.getRolledupRecordTitles("Members (display)"),
|
||||||
memberIds: page.getRelationIds("Members"),
|
memberIds: page.getRelationIds("Members"),
|
||||||
createdAt: some(parseIso8601(page["created_time"].getStr)),
|
createdAt: some(parseIso8601(page["created_time"].getStr)),
|
||||||
lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)))
|
lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)))
|
||||||
|
|
||||||
proc personFromPage*(page: JsonNode): Person =
|
proc personFromPage*(page: JsonNode): Person =
|
||||||
|
let marriedToIds = page.getRelationIds("Married To")
|
||||||
|
|
||||||
result = Person(
|
result = Person(
|
||||||
id: page["id"].getStr,
|
id: page["id"].getStr,
|
||||||
preferredName: page.getTitle("Preferred Name"),
|
preferredName: page.getTitle("Preferred Name"),
|
||||||
@ -201,10 +216,16 @@ proc personFromPage*(page: JsonNode): Person =
|
|||||||
primaryPhoneNumber: page.getPhone("Primary Phone Number"),
|
primaryPhoneNumber: page.getPhone("Primary Phone Number"),
|
||||||
primaryEmailAddress: page.getEmail("Email Address"),
|
primaryEmailAddress: page.getEmail("Email Address"),
|
||||||
relationshipToHff: page.getMultiSelect("Relationship to HFF"),
|
relationshipToHff: page.getMultiSelect("Relationship to HFF"),
|
||||||
|
addresses: page.getRollupArrayValues("Full Address").mapIt(it{"formula", "string"}.getStr),
|
||||||
addressIds: page.getRelationIds("Address"),
|
addressIds: page.getRelationIds("Address"),
|
||||||
marriedToId: page.getRelationIds("Married To"),
|
marriedTo: if marriedToIds.len == 0: ""
|
||||||
|
else: page.getRolledupRecordTitles("Married To (display)")[0],
|
||||||
|
marriedToId: if marriedToIds.len == 0: ""
|
||||||
|
else: marriedToIds[0],
|
||||||
anniversary: page.getDateTime("Anniversary"),
|
anniversary: page.getDateTime("Anniversary"),
|
||||||
|
parents: page.getRolledupRecordTitles("Parents (display)"),
|
||||||
parentIds: page.getRelationIds("Parents"),
|
parentIds: page.getRelationIds("Parents"),
|
||||||
|
children: page.getRolledupRecordTitles("Children (display)"),
|
||||||
childIds: page.getRelationIds("Children"),
|
childIds: page.getRelationIds("Children"),
|
||||||
createdAt: some(parseIso8601(page["created_time"].getStr)),
|
createdAt: some(parseIso8601(page["created_time"].getStr)),
|
||||||
lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)),
|
lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)),
|
||||||
|
@ -1,9 +1,16 @@
|
|||||||
import std/json, std/options, std/sequtils, std/times
|
import std/json, std/logging, std/options, std/sequtils, std/times
|
||||||
|
import namespaced_logging
|
||||||
import timeutils
|
import timeutils
|
||||||
|
|
||||||
const NOTION_MAX_PAGE_SIZE* = 100
|
const NOTION_MAX_PAGE_SIZE* = 100
|
||||||
const NOTION_DATE_FORMAT = "YYYY-MM-dd"
|
const NOTION_DATE_FORMAT = "YYYY-MM-dd"
|
||||||
|
|
||||||
|
var logNs {.threadvar.}: LoggingNamespace
|
||||||
|
|
||||||
|
template log(): untyped =
|
||||||
|
if logNs.isNil: logNs = initLoggingNamespace("hff_notion_api_client/utils", lvlInfo)
|
||||||
|
logNs
|
||||||
|
|
||||||
proc parseDate(str: string): DateTime =
|
proc parseDate(str: string): DateTime =
|
||||||
try: result = parseIso8601(str)
|
try: result = parseIso8601(str)
|
||||||
except: result = times.parse(str, NOTION_DATE_FORMAT)
|
except: result = times.parse(str, NOTION_DATE_FORMAT)
|
||||||
@ -50,7 +57,7 @@ proc makeTextProp*(propType: string, value: string): JsonNode =
|
|||||||
## Utility functions for reading Page property values
|
## Utility functions for reading Page property values
|
||||||
## --------------------------------------------------
|
## --------------------------------------------------
|
||||||
|
|
||||||
proc getPropNode(page: JsonNode, propType, propName: string): JsonNode =
|
proc getPropNode*(page: JsonNode, propType, propName: string): JsonNode =
|
||||||
result = page{"properties", propName, propType}
|
result = page{"properties", propName, propType}
|
||||||
|
|
||||||
if isNil(result):
|
if isNil(result):
|
||||||
@ -74,6 +81,22 @@ proc getRelationIds*(page: JsonNode, propName: string): seq[string] =
|
|||||||
let propNode = page.getPropNode("relation", propName)
|
let propNode = page.getPropNode("relation", propName)
|
||||||
return propNode.getElems.mapIt(it["id"].getStr)
|
return propNode.getElems.mapIt(it["id"].getStr)
|
||||||
|
|
||||||
|
proc getRollupArrayValues*(page: JsonNode, propName: string): seq[JsonNode] =
|
||||||
|
return page.getPropNode("rollup", propName){"array"}.getElems(@[])
|
||||||
|
|
||||||
|
proc getRolledupRecordTitles*(page: JsonNode, propName: string): seq[string] =
|
||||||
|
let rollups = page.getPropNode("rollup", propName)["array"]
|
||||||
|
if rollups.getElems.len == 0: return @[]
|
||||||
|
elif rollups.getElems.len != 1 or not rollups.getElems[0].hasKey("title"):
|
||||||
|
log().debug "Expected exactly one item of type 'title'. Received: \n" & rollups.pretty
|
||||||
|
raise newException(
|
||||||
|
ValueError,
|
||||||
|
"unexpected format of rollup value for '" & propName & "' property")
|
||||||
|
|
||||||
|
let titleElems = rollups.getElems[0]["title"]
|
||||||
|
|
||||||
|
return titleElems.getElems.mapIt(it["plain_text"].getStr)
|
||||||
|
|
||||||
proc getText*(page: JsonNode, propName: string): string =
|
proc getText*(page: JsonNode, propName: string): string =
|
||||||
let propNode = page.getPropNode("rich_text", propName)
|
let propNode = page.getPropNode("rich_text", propName)
|
||||||
if propNode.len == 0: return ""
|
if propNode.len == 0: return ""
|
||||||
|
Reference in New Issue
Block a user