Skip to main content

max / balanced_breakfast

3.8 KB · 163 lines History Blame Raw
1 // NASA Astronomy Picture of the Day. Fetches random recent APODs from the
2 // NASA planetary API. Uses DEMO_KEY by default (30 req/hr); supports both
3 // image and video media types. Displays HD image when available.
4
5 const NASA_API = "https://api.nasa.gov/planetary/apod";
6
7 fn id() {
8 "nasa_apod"
9 }
10
11 fn name() {
12 "NASA APOD"
13 }
14
15 fn capabilities() {
16 #{
17 supports_pagination: false
18 }
19 }
20
21 fn config_schema() {
22 #{
23 description: "NASA Astronomy Picture of the Day. Shows stunning space images with expert explanations. Uses the free DEMO_KEY by default (30 req/hr). Provide your own API key from api.nasa.gov for higher limits.",
24 fields: [
25 #{
26 key: "api_key",
27 label: "API Key",
28 field_type: "text",
29 description: "NASA API key (leave blank to use DEMO_KEY)",
30 default_value: "DEMO_KEY",
31 placeholder: "DEMO_KEY"
32 },
33 #{
34 key: "count",
35 label: "Number of images",
36 field_type: "text",
37 description: "How many recent APODs to fetch (max 10)",
38 default_value: "5",
39 placeholder: "5"
40 }
41 ]
42 }
43 }
44
45 fn fetch(config, cursor) {
46 let api_key = "DEMO_KEY";
47 if config.api_key != () && config.api_key != "" {
48 api_key = config.api_key;
49 }
50
51 let count = 5;
52 if config.count != () {
53 let parsed = parse_int(config.count);
54 if parsed != () && parsed > 0 {
55 if parsed > 10 {
56 count = 10;
57 } else {
58 count = parsed;
59 }
60 }
61 }
62
63 let url = NASA_API + "?api_key=" + api_key + "&count=" + count + "&thumbs=true";
64 let results = http_get_json(url);
65
66 if results == () {
67 return #{ items: [], has_more: false };
68 }
69
70 let items = [];
71 for entry in results {
72 let item = parse_apod(entry);
73 if item != () {
74 items.push(item);
75 }
76 }
77
78 #{
79 items: items,
80 has_more: false
81 }
82 }
83
84 fn parse_apod(entry) {
85 let title = "Untitled";
86 if entry.title != () {
87 title = entry.title;
88 }
89
90 let explanation = "";
91 if entry.explanation != () {
92 explanation = entry.explanation;
93 }
94
95 let date = "";
96 if entry.date != () {
97 date = entry.date;
98 }
99
100 let media_type = "image";
101 if entry.media_type != () {
102 media_type = entry.media_type;
103 }
104
105 let url = "";
106 if entry.url != () {
107 url = entry.url;
108 }
109
110 let hdurl = "";
111 if entry.hdurl != () {
112 hdurl = entry.hdurl;
113 }
114
115 // Build body with image and explanation
116 let body = "";
117 if media_type == "image" {
118 let img_url = url;
119 if hdurl != "" {
120 img_url = hdurl;
121 }
122 body = `<img src="` + img_url + `" alt="` + title + `" style="max-width:100%">`;
123 } else if media_type == "video" {
124 body = "Video: " + url;
125 }
126
127 if explanation != "" {
128 body += "\n\n" + explanation;
129 }
130
131 let copyright = "";
132 if entry.copyright != () {
133 copyright = str_trim(entry.copyright);
134 }
135
136 let secondary = date;
137 if copyright != "" {
138 secondary += " · " + copyright;
139 }
140
141 let apod_url = "https://apod.nasa.gov/apod/";
142
143 #{
144 id: #{ source: "nasa_apod", item_id: date },
145 bite: #{
146 author: "NASA",
147 text: truncate(title, 100),
148 secondary: secondary,
149 indicator: "🔭"
150 },
151 content: #{
152 title: title,
153 body: body,
154 url: apod_url
155 },
156 meta: #{
157 source_name: "NASA APOD",
158 published_at: timestamp_now(),
159 tags: ["nasa", "astronomy", "space"]
160 }
161 }
162 }
163