pyrtan / examples / hacker-news / hacker-news-item.toml
1,694 bytes · last changed 2026-10-26 in The catalog grows up: namespaces, publishing by pull request through the gate, gap reports gossiped back to authors; release 0.8.0
| 1 | name = "hacker-news-item" |
| 2 | version = 2 |
| 3 | namespace = "pyrtan" |
| 4 | description = "One Hacker News item by id: title, url, score, author." |
| 5 | tags = ["news", "read-only"] |
| 6 | license = "MIT" |
| 7 | hosts = ["hacker-news.firebaseio.com"] |
| 8 | start = "fetch" |
| 9 | |
| 10 | [[triggers]] |
| 11 | pattern = "hacker news item {id:int}" |
| 12 | |
| 13 | [inputs.id] |
| 14 | type = "int" |
| 15 | min = 1 |
| 16 | description = "The item id" |
| 17 | |
| 18 | [nodes.fetch] |
| 19 | kind = "observe" |
| 20 | http = { method = "GET", url = "https://hacker-news.firebaseio.com/v0/item/{{ inputs.id }}.json" } |
| 21 | into = "resp" |
| 22 | extract = [ |
| 23 | { into = "title", json = "json.title" }, |
| 24 | { into = "url", json = "json.url" }, |
| 25 | { into = "score", json = "json.score" }, |
| 26 | { into = "by", json = "json.by" }, |
| 27 | { into = "type", json = "json.type" }, |
| 28 | ] |
| 29 | next = "kind" |
| 30 | |
| 31 | [nodes.kind] |
| 32 | kind = "decide" |
| 33 | on = "type" |
| 34 | branches = [ |
| 35 | { when = { eq = "story" }, then = "has-url" }, |
| 36 | { when = { eq = "job" }, then = "has-url" }, |
| 37 | { when = { exists = false }, then = "missing" }, |
| 38 | { else = "not-a-story" }, |
| 39 | ] |
| 40 | |
| 41 | [nodes.has-url] |
| 42 | kind = "decide" |
| 43 | on = "url" |
| 44 | branches = [ |
| 45 | { when = { exists = true }, then = "reply" }, |
| 46 | { else = "self-post" }, |
| 47 | ] |
| 48 | |
| 49 | [nodes.self-post] |
| 50 | kind = "set" |
| 51 | set = { url = "https://news.ycombinator.com/item?id={{ inputs.id }}" } |
| 52 | next = "reply" |
| 53 | |
| 54 | [nodes.reply] |
| 55 | kind = "done" |
| 56 | say = "{{ state.title }} ({{ state.score }} points, by {{ state.by }}) {{ state.url }}" |
| 57 | output = { id = "{{ inputs.id }}", title = "{{ state.title }}", url = "{{ state.url }}", score = "{{ state.score }}", by = "{{ state.by }}" } |
| 58 | |
| 59 | [nodes.missing] |
| 60 | kind = "fail" |
| 61 | reason = "no-such-item" |
| 62 | say = "There is no Hacker News item {{ inputs.id }}." |
| 63 | |
| 64 | [nodes.not-a-story] |
| 65 | kind = "fail" |
| 66 | reason = "not-a-story" |
| 67 | say = "Item {{ inputs.id }} is a {{ state.type }}, not a story." |