og_pilot_ruby 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +466 -0
- data/lib/og_pilot_ruby/client.rb +31 -1
- data/lib/og_pilot_ruby/configuration.rb +3 -1
- data/lib/og_pilot_ruby/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 367bb4f8ea0c4a82c261f4403a42ae5bbf2afa25069bad87250c884ca343526b
|
|
4
|
+
data.tar.gz: 753f95ace14cc5d6b1895a286174810457837ba9e7b0fdb2dcb646bfa9f8ea78
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ec298c3d0d781c259aece2d385f1f53a0e26633295b0bc8b1624ab85123a6cb5840a0b4f81a4e303940c425b618d270b8f504e19cb7654466046c11dbbda666b
|
|
7
|
+
data.tar.gz: 29008c57e899486428e21c2395e0f3cdfc2010d1bc533cd93102e0ba17a41cabc96c94295bf4b3a46247ebe8a6ff5e183a7981e6c8d540406cbea3e22e29eb9f
|
data/README.md
CHANGED
|
@@ -29,6 +29,8 @@ OgPilotRuby.configure do |config|
|
|
|
29
29
|
config.api_key = ENV.fetch("OG_PILOT_API_KEY")
|
|
30
30
|
config.domain = ENV.fetch("OG_PILOT_DOMAIN")
|
|
31
31
|
# config.strip_extensions = true
|
|
32
|
+
# config.cache_store = Rails.cache
|
|
33
|
+
# config.cache_ttl = 86_400
|
|
32
34
|
end
|
|
33
35
|
```
|
|
34
36
|
|
|
@@ -61,6 +63,12 @@ image_url = OgPilotRuby.create_image(
|
|
|
61
63
|
If you omit `iat`, OG Pilot will cache the image indefinitely. Provide an `iat` to
|
|
62
64
|
refresh the cache daily.
|
|
63
65
|
|
|
66
|
+
When `config.cache_store` is set, the client can also cache generated responses
|
|
67
|
+
locally:
|
|
68
|
+
|
|
69
|
+
- With `iat`: cache for `cache_ttl` seconds
|
|
70
|
+
- Without `iat`: cache for `7 * cache_ttl` seconds
|
|
71
|
+
|
|
64
72
|
### Fail-safe behavior
|
|
65
73
|
|
|
66
74
|
`create_image` is non-blocking. If any error occurs (request, configuration,
|
|
@@ -73,6 +81,7 @@ error-level message instead.
|
|
|
73
81
|
### Template helpers
|
|
74
82
|
|
|
75
83
|
`create_image` defaults to the `page` template when `template` is omitted.
|
|
84
|
+
Supported templates: `page`, `blog_post`, `podcast`, `product`, `event`, `book`, `company`, `portfolio`, `github`.
|
|
76
85
|
|
|
77
86
|
Use these helpers to force a specific template:
|
|
78
87
|
|
|
@@ -83,6 +92,7 @@ Use these helpers to force a specific template:
|
|
|
83
92
|
- `OgPilotRuby.create_book_image(...)`
|
|
84
93
|
- `OgPilotRuby.create_company_image(...)`
|
|
85
94
|
- `OgPilotRuby.create_portfolio_image(...)`
|
|
95
|
+
- For `github`, use `OgPilotRuby.create_image(template: "github", ...)` (no dedicated helper yet).
|
|
86
96
|
|
|
87
97
|
Example:
|
|
88
98
|
|
|
@@ -94,6 +104,439 @@ image_url = OgPilotRuby.create_blog_post_image(
|
|
|
94
104
|
)
|
|
95
105
|
```
|
|
96
106
|
|
|
107
|
+
<!-- OG_SAMPLES_START -->
|
|
108
|
+
## OG Image Examples
|
|
109
|
+
|
|
110
|
+
All sample payloads set explicit `bg_color`, `text_color`, and logo/avatar URLs to avoid default branding fallbacks.
|
|
111
|
+
|
|
112
|
+
For templates that support custom images, this set includes both `with_custom_image` and `without_custom_image` variants. (`github` currently has no custom image slot.)
|
|
113
|
+
|
|
114
|
+
Avatar-style fields (for example `author_avatar_url`) use DiceBear Avataaars, e.g. `https://api.dicebear.com/7.x/avataaars/svg?seed=JaneSmith`.
|
|
115
|
+
|
|
116
|
+
### Sample Gallery
|
|
117
|
+
|
|
118
|
+
| Template | Variant | Preview |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| `page` | `with custom image` |  |
|
|
121
|
+
| `page` | `without custom image` |  |
|
|
122
|
+
| `blog_post` | `with custom image` |  |
|
|
123
|
+
| `blog_post` | `without custom image` |  |
|
|
124
|
+
| `podcast` | `with custom image` |  |
|
|
125
|
+
| `podcast` | `without custom image` |  |
|
|
126
|
+
| `product` | `with custom image` |  |
|
|
127
|
+
| `product` | `without custom image` |  |
|
|
128
|
+
| `event` | `with custom image` |  |
|
|
129
|
+
| `event` | `without custom image` |  |
|
|
130
|
+
| `book` | `with custom image` |  |
|
|
131
|
+
| `book` | `without custom image` |  |
|
|
132
|
+
| `portfolio` | `with custom image` |  |
|
|
133
|
+
| `portfolio` | `without custom image` |  |
|
|
134
|
+
| `company` | `with custom image` |  |
|
|
135
|
+
| `company` | `without custom image` |  |
|
|
136
|
+
| `github` | `default` |  |
|
|
137
|
+
|
|
138
|
+
### Parameters Used
|
|
139
|
+
|
|
140
|
+
<details>
|
|
141
|
+
<summary>Exact payloads for these samples</summary>
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
[
|
|
145
|
+
{
|
|
146
|
+
"id": "page_with_custom_image",
|
|
147
|
+
"template": "page",
|
|
148
|
+
"variant": "with_custom_image",
|
|
149
|
+
"params": {
|
|
150
|
+
"title": "Acme Robotics Product Updates",
|
|
151
|
+
"description": "See what shipped this week across the web app.",
|
|
152
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Fwww.notion.so",
|
|
153
|
+
"image_url": "https://images.unsplash.com/photo-1558655146-d09347e92766?w=1400&q=80",
|
|
154
|
+
"bg_color": "#0B1220",
|
|
155
|
+
"text_color": "#F8FAFC",
|
|
156
|
+
"template": "page"
|
|
157
|
+
},
|
|
158
|
+
"image_url": "https://img.ogpilot.com/1f6oY498I6SiNfqGDjwdHLNpwmeU264t2OL0k7tY8Mw/plain/s3://og-pilot-development/eoo5v45d766hf22j4r2al60ktali"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"id": "page_without_custom_image",
|
|
162
|
+
"template": "page",
|
|
163
|
+
"variant": "without_custom_image",
|
|
164
|
+
"params": {
|
|
165
|
+
"title": "Notion AI Workspace for Product Teams",
|
|
166
|
+
"description": "Docs, specs, and roadmaps in one living workspace.",
|
|
167
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Fwww.notion.so",
|
|
168
|
+
"bg_color": "#111827",
|
|
169
|
+
"text_color": "#E5E7EB",
|
|
170
|
+
"template": "page"
|
|
171
|
+
},
|
|
172
|
+
"image_url": "https://img.ogpilot.com/9MZdTcTRyOoRqpTLll__EvDimmgojZESfZWokDqXeZM/plain/s3://og-pilot-development/wfa9es2wuvp6btjiriekk53swp6n"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"id": "blog_post_with_custom_image",
|
|
176
|
+
"template": "blog_post",
|
|
177
|
+
"variant": "with_custom_image",
|
|
178
|
+
"params": {
|
|
179
|
+
"title": "How Stripe Reduced Checkout Abandonment by 18%",
|
|
180
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Fstripe.com",
|
|
181
|
+
"image_url": "https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=1400&q=80",
|
|
182
|
+
"author_name": "Maya Patel",
|
|
183
|
+
"author_avatar_url": "https://api.dicebear.com/7.x/avataaars/svg?seed=MayaPatel",
|
|
184
|
+
"publish_date": "2026-02-24",
|
|
185
|
+
"bg_color": "#0F172A",
|
|
186
|
+
"text_color": "#F8FAFC",
|
|
187
|
+
"template": "blog_post"
|
|
188
|
+
},
|
|
189
|
+
"image_url": "https://img.ogpilot.com/RBBQZnBrAKcVmFjJg6UtNqX8P6nRRQdGLrlJNWYif7I/plain/s3://og-pilot-development/je7pj816exul9umhyszqpnbxelmd"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"id": "blog_post_without_custom_image",
|
|
193
|
+
"template": "blog_post",
|
|
194
|
+
"variant": "without_custom_image",
|
|
195
|
+
"params": {
|
|
196
|
+
"title": "Inside Vercel's Edge Rendering Playbook",
|
|
197
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Fvercel.com",
|
|
198
|
+
"author_name": "Daniel Kim",
|
|
199
|
+
"author_avatar_url": "https://api.dicebear.com/7.x/avataaars/svg?seed=DanielKim",
|
|
200
|
+
"publish_date": "2026-02-18",
|
|
201
|
+
"bg_color": "#111827",
|
|
202
|
+
"text_color": "#E5E7EB",
|
|
203
|
+
"template": "blog_post"
|
|
204
|
+
},
|
|
205
|
+
"image_url": "https://img.ogpilot.com/yP1B7OrLOy9Iu9JDSNk9Veys3ESCuCSBM9il2wq13V4/plain/s3://og-pilot-development/6aei8frvun6kvqojoor1hqack31y"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"id": "podcast_with_custom_image",
|
|
209
|
+
"template": "podcast",
|
|
210
|
+
"variant": "with_custom_image",
|
|
211
|
+
"params": {
|
|
212
|
+
"title": "Indie Hackers Podcast: Pricing Experiments That Worked",
|
|
213
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Fwww.spotify.com",
|
|
214
|
+
"image_url": "https://images.unsplash.com/photo-1478737270239-2f02b77fc618?w=1400&q=80",
|
|
215
|
+
"episode_date": "2026-02-21",
|
|
216
|
+
"bg_color": "#18181B",
|
|
217
|
+
"text_color": "#FAFAFA",
|
|
218
|
+
"template": "podcast"
|
|
219
|
+
},
|
|
220
|
+
"image_url": "https://img.ogpilot.com/rzOOt7PWJ44OEwpKnntMLZaPvtl76DA3yRlj6B6N-Cc/plain/s3://og-pilot-development/fmkeblwertneuy4p82foeg5rfltl"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"id": "podcast_without_custom_image",
|
|
224
|
+
"template": "podcast",
|
|
225
|
+
"variant": "without_custom_image",
|
|
226
|
+
"params": {
|
|
227
|
+
"title": "Shopify Masters: Building a 7-Figure DTC Brand",
|
|
228
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Fwww.shopify.com",
|
|
229
|
+
"episode_date": "2026-02-19",
|
|
230
|
+
"bg_color": "#0B1120",
|
|
231
|
+
"text_color": "#E2E8F0",
|
|
232
|
+
"template": "podcast"
|
|
233
|
+
},
|
|
234
|
+
"image_url": "https://img.ogpilot.com/5UWWFG2J5bNRDOhDkN96ZG_g0XI9ULGDFgQkuVTjCYQ/plain/s3://og-pilot-development/yyhmo7lamj1n99i2n6dyttwungmq"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"id": "product_with_custom_image",
|
|
238
|
+
"template": "product",
|
|
239
|
+
"variant": "with_custom_image",
|
|
240
|
+
"params": {
|
|
241
|
+
"title": "Allbirds Tree Dasher 3",
|
|
242
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Fwww.allbirds.com",
|
|
243
|
+
"image_url": "https://images.unsplash.com/photo-1542291026-7eec264c27ff?w=1400&q=80",
|
|
244
|
+
"unique_selling_point": "Free shipping + 30-day returns",
|
|
245
|
+
"bg_color": "#F8FAFC",
|
|
246
|
+
"text_color": "#0F172A",
|
|
247
|
+
"template": "product"
|
|
248
|
+
},
|
|
249
|
+
"image_url": "https://img.ogpilot.com/mzmHDMjyAX4VlpJanMT3zpmIJgSuClYI5eofhFpSJNQ/plain/s3://og-pilot-development/8ls2legb316l9vak40nu388uzy2t"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"id": "product_without_custom_image",
|
|
253
|
+
"template": "product",
|
|
254
|
+
"variant": "without_custom_image",
|
|
255
|
+
"params": {
|
|
256
|
+
"title": "Bose QuietComfort Ultra",
|
|
257
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Fwww.bose.com",
|
|
258
|
+
"unique_selling_point": "Save $70 this weekend",
|
|
259
|
+
"bg_color": "#111827",
|
|
260
|
+
"text_color": "#F9FAFB",
|
|
261
|
+
"template": "product"
|
|
262
|
+
},
|
|
263
|
+
"image_url": "https://img.ogpilot.com/kK6d7xU3EWT5WKC6jKCw1rhJDmv9bwvRn2S-nShV4NA/plain/s3://og-pilot-development/52ns2l1ll7hjhfg0p3wn5c9pqtr5"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"id": "event_with_custom_image",
|
|
267
|
+
"template": "event",
|
|
268
|
+
"variant": "with_custom_image",
|
|
269
|
+
"params": {
|
|
270
|
+
"title": "Launch Week Berlin 2026",
|
|
271
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Fwww.eventbrite.com",
|
|
272
|
+
"image_url": "https://images.unsplash.com/photo-1540575467063-178a50c2df87?w=1400&q=80",
|
|
273
|
+
"event_date": "2026-06-12/2026-06-14",
|
|
274
|
+
"event_location": "Station Berlin",
|
|
275
|
+
"bg_color": "#1E1B4B",
|
|
276
|
+
"text_color": "#F5F3FF",
|
|
277
|
+
"template": "event"
|
|
278
|
+
},
|
|
279
|
+
"image_url": "https://img.ogpilot.com/A7nxHkYs4xN4c1PhH2KQSWoB4ALwBdpP0HPiAss9_70/plain/s3://og-pilot-development/vjkdf6cx82dvdxmhiwtvrvkl976d"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"id": "event_without_custom_image",
|
|
283
|
+
"template": "event",
|
|
284
|
+
"variant": "without_custom_image",
|
|
285
|
+
"params": {
|
|
286
|
+
"title": "RubyConf Chicago 2026",
|
|
287
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Frubyconf.org",
|
|
288
|
+
"event_date": "2026-11-17",
|
|
289
|
+
"event_location": "Chicago, IL",
|
|
290
|
+
"bg_color": "#312E81",
|
|
291
|
+
"text_color": "#EEF2FF",
|
|
292
|
+
"template": "event"
|
|
293
|
+
},
|
|
294
|
+
"image_url": "https://img.ogpilot.com/elpfu28vJ57XCGx3npKhCwXqqJnPoqwCm8Aj5SLkWsM/plain/s3://og-pilot-development/vpte818nvtegc60ta98q7pmw91c8"
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
"id": "book_with_custom_image",
|
|
298
|
+
"template": "book",
|
|
299
|
+
"variant": "with_custom_image",
|
|
300
|
+
"params": {
|
|
301
|
+
"title": "Designing APIs for Humans",
|
|
302
|
+
"description": "A practical handbook for product-minded engineers.",
|
|
303
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Fwww.oreilly.com",
|
|
304
|
+
"image_url": "https://images.unsplash.com/photo-1512820790803-83ca734da794?w=1400&q=80",
|
|
305
|
+
"book_author": "Alex Turner",
|
|
306
|
+
"book_series_number": "2",
|
|
307
|
+
"book_genre": "Technology",
|
|
308
|
+
"bg_color": "#172554",
|
|
309
|
+
"text_color": "#EFF6FF",
|
|
310
|
+
"template": "book"
|
|
311
|
+
},
|
|
312
|
+
"image_url": "https://img.ogpilot.com/7pidSkvU_l0RzY9xBOLSa2x-jDWWvx14Gtv-KMDCGLw/plain/s3://og-pilot-development/cwnhb631ls2olk0yzkukmr5dnf7e"
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"id": "book_without_custom_image",
|
|
316
|
+
"template": "book",
|
|
317
|
+
"variant": "without_custom_image",
|
|
318
|
+
"params": {
|
|
319
|
+
"title": "The Product Operating System",
|
|
320
|
+
"description": "How modern teams ship with confidence.",
|
|
321
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Fwww.penguinrandomhouse.com",
|
|
322
|
+
"book_author": "Sofia Ramirez",
|
|
323
|
+
"book_series_number": "1",
|
|
324
|
+
"book_genre": "Business",
|
|
325
|
+
"bg_color": "#1E293B",
|
|
326
|
+
"text_color": "#F8FAFC",
|
|
327
|
+
"template": "book"
|
|
328
|
+
},
|
|
329
|
+
"image_url": "https://img.ogpilot.com/FpMbBN15SLgaK9FEX07xXcT5dQIWyZkFdHaZ9i5wx3U/plain/s3://og-pilot-development/0rzisfn2qswdzsz641rl3s29ngu9"
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
"id": "portfolio_with_custom_image",
|
|
333
|
+
"template": "portfolio",
|
|
334
|
+
"variant": "with_custom_image",
|
|
335
|
+
"params": {
|
|
336
|
+
"title": "Maya Chen • Product Designer",
|
|
337
|
+
"description": "Fintech UX, design systems, and prototyping.",
|
|
338
|
+
"logo_url": "https://api.dicebear.com/7.x/avataaars/svg?seed=MayaChen&size=64",
|
|
339
|
+
"image_url": "https://images.unsplash.com/photo-1557672172-298e090bd0f1?w=1400&q=80",
|
|
340
|
+
"bg_color": "#1F2937",
|
|
341
|
+
"text_color": "#F9FAFB",
|
|
342
|
+
"template": "portfolio"
|
|
343
|
+
},
|
|
344
|
+
"image_url": "https://img.ogpilot.com/gauiw2MMcNLLSFnQ07Hq3flv4S0L-89lnnjUOO0VgYU/plain/s3://og-pilot-development/qok04llq0ff3d2lherudwlhqxslm"
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
"id": "portfolio_without_custom_image",
|
|
348
|
+
"template": "portfolio",
|
|
349
|
+
"variant": "without_custom_image",
|
|
350
|
+
"params": {
|
|
351
|
+
"title": "Arjun Rao • Frontend Engineer",
|
|
352
|
+
"description": "React performance, accessibility, and DX.",
|
|
353
|
+
"logo_url": "https://api.dicebear.com/7.x/avataaars/svg?seed=ArjunRao&size=64",
|
|
354
|
+
"bg_color": "#0F172A",
|
|
355
|
+
"text_color": "#E2E8F0",
|
|
356
|
+
"template": "portfolio"
|
|
357
|
+
},
|
|
358
|
+
"image_url": "https://img.ogpilot.com/jVck9SDPlei0gaHq44_itLoVzn2wINrCP3XCTQF3SYs/plain/s3://og-pilot-development/jxa1s7dtibaeqamh0fsymwz7uqrx"
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
"id": "company_with_custom_image",
|
|
362
|
+
"template": "company",
|
|
363
|
+
"variant": "with_custom_image",
|
|
364
|
+
"params": {
|
|
365
|
+
"title": "Notion",
|
|
366
|
+
"description": "4 job openings",
|
|
367
|
+
"logo_url": "https://www.google.com/s2/favicons?sz=128&domain_url=https%3A%2F%2Fwww.notion.so",
|
|
368
|
+
"bg_color": "#111827",
|
|
369
|
+
"text_color": "#F9FAFB",
|
|
370
|
+
"template": "company"
|
|
371
|
+
},
|
|
372
|
+
"image_url": "https://img.ogpilot.com/rji7hNgoxRM1KF2GofIO9gqXJQNg5CqlPWbhbGpR4FA/plain/s3://og-pilot-development/2xl6zi3zgjm74izr46efduzhmbrr"
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
"id": "company_without_custom_image",
|
|
376
|
+
"template": "company",
|
|
377
|
+
"variant": "without_custom_image",
|
|
378
|
+
"params": {
|
|
379
|
+
"title": "Linear",
|
|
380
|
+
"description": "12 job openings",
|
|
381
|
+
"company_logo_url": "https://www.google.com/s2/favicons?sz=256&domain_url=https%3A%2F%2Flinear.app",
|
|
382
|
+
"bg_color": "#0B1220",
|
|
383
|
+
"text_color": "#E5E7EB",
|
|
384
|
+
"template": "company",
|
|
385
|
+
"iss": "gitdigest.ai"
|
|
386
|
+
},
|
|
387
|
+
"image_url": "https://img.ogpilot.com/PgGl9a6xPmG0Tn7qKmZZUczrv43cNLxzyISsbHG8_oE/plain/s3://og-pilot-development/6gmm6jg5r8ya27r3tr215edfd972"
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
"id": "github_activity",
|
|
391
|
+
"template": "github",
|
|
392
|
+
"variant": "default",
|
|
393
|
+
"params": {
|
|
394
|
+
"title": "rails/rails",
|
|
395
|
+
"description": "Recent merged PRs, reviews, and commit activity.",
|
|
396
|
+
"accent_color": "#22C55E",
|
|
397
|
+
"bg_color": "#0B1220",
|
|
398
|
+
"text_color": "#E5E7EB",
|
|
399
|
+
"contributions": [
|
|
400
|
+
{
|
|
401
|
+
"date": "2025-10-28",
|
|
402
|
+
"count": 6
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
"date": "2025-11-01",
|
|
406
|
+
"count": 3
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
"date": "2025-11-05",
|
|
410
|
+
"count": 9
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"date": "2025-11-08",
|
|
414
|
+
"count": 12
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
"date": "2025-11-12",
|
|
418
|
+
"count": 7
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
"date": "2025-11-16",
|
|
422
|
+
"count": 11
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
"date": "2025-11-20",
|
|
426
|
+
"count": 5
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
"date": "2025-11-24",
|
|
430
|
+
"count": 14
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
"date": "2025-11-28",
|
|
434
|
+
"count": 8
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
"date": "2025-12-02",
|
|
438
|
+
"count": 4
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
"date": "2025-12-06",
|
|
442
|
+
"count": 10
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
"date": "2025-12-10",
|
|
446
|
+
"count": 15
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
"date": "2025-12-14",
|
|
450
|
+
"count": 6
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
"date": "2025-12-18",
|
|
454
|
+
"count": 9
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
"date": "2025-12-22",
|
|
458
|
+
"count": 13
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
"date": "2025-12-26",
|
|
462
|
+
"count": 4
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
"date": "2025-12-30",
|
|
466
|
+
"count": 7
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
"date": "2026-01-03",
|
|
470
|
+
"count": 11
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
"date": "2026-01-07",
|
|
474
|
+
"count": 16
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
"date": "2026-01-11",
|
|
478
|
+
"count": 12
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
"date": "2026-01-15",
|
|
482
|
+
"count": 6
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
"date": "2026-01-19",
|
|
486
|
+
"count": 8
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
"date": "2026-01-23",
|
|
490
|
+
"count": 14
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
"date": "2026-01-27",
|
|
494
|
+
"count": 9
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"date": "2026-01-31",
|
|
498
|
+
"count": 5
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
"date": "2026-02-04",
|
|
502
|
+
"count": 13
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
"date": "2026-02-08",
|
|
506
|
+
"count": 17
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
"date": "2026-02-12",
|
|
510
|
+
"count": 10
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
"date": "2026-02-16",
|
|
514
|
+
"count": 7
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
"date": "2026-02-20",
|
|
518
|
+
"count": 12
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
"date": "2026-02-24",
|
|
522
|
+
"count": 9
|
|
523
|
+
}
|
|
524
|
+
],
|
|
525
|
+
"template": "github"
|
|
526
|
+
},
|
|
527
|
+
"image_url": "https://img.ogpilot.com/0dxm83dTyNCg5Dq_GZFT4SqsRyTWUO31d0HQwjIq0-A/plain/s3://og-pilot-development/jlhwskjsx08x56attaljw3ce0p65"
|
|
528
|
+
}
|
|
529
|
+
]
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
</details>
|
|
533
|
+
|
|
534
|
+
<!-- OG_SAMPLES_END -->
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
|
|
97
540
|
## Parameters
|
|
98
541
|
|
|
99
542
|
The client sends `POST /api/v1/images` requests. All parameters are embedded in the signed JWT payload; the only query param is `token`.
|
|
@@ -123,6 +566,8 @@ The gem handles `iss` (domain) and `sub` (API key prefix) automatically.
|
|
|
123
566
|
| `open_timeout` | `5` | Connection timeout in seconds |
|
|
124
567
|
| `read_timeout` | `10` | Read timeout in seconds |
|
|
125
568
|
| `strip_extensions` | `true` | When `true`, file extensions are stripped from resolved paths (see [Strip extensions](#strip-extensions)) |
|
|
569
|
+
| `cache_store` | `nil` | Optional cache backend with `read`/`write` (for example `Rails.cache`) |
|
|
570
|
+
| `cache_ttl` | `86400` | Cache TTL in seconds when `cache_store` is enabled |
|
|
126
571
|
|
|
127
572
|
### Ruby options
|
|
128
573
|
|
|
@@ -144,6 +589,7 @@ The gem handles `iss` (domain) and `sub` (API key prefix) automatically.
|
|
|
144
589
|
| `book` | `title`, `description`, `book_author`, `book_series_number`, `book_description`, `book_genre` |
|
|
145
590
|
| `portfolio` | `title` |
|
|
146
591
|
| `company` | `title`, `company_logo_url`, `description` (note: `image_url` is ignored) |
|
|
592
|
+
| `github` | `title`, `description`, `contributions` (array of `{ date, count }`), `accent_color` |
|
|
147
593
|
|
|
148
594
|
### Path handling
|
|
149
595
|
|
|
@@ -188,6 +634,26 @@ payload = {
|
|
|
188
634
|
data = OgPilotRuby.create_image(**payload, json: true)
|
|
189
635
|
```
|
|
190
636
|
|
|
637
|
+
### Local caching
|
|
638
|
+
|
|
639
|
+
You can optionally enable client-side caching to avoid repeated API calls for
|
|
640
|
+
identical payloads:
|
|
641
|
+
|
|
642
|
+
```ruby
|
|
643
|
+
OgPilotRuby.configure do |config|
|
|
644
|
+
config.cache_store = Rails.cache
|
|
645
|
+
config.cache_ttl = 86_400 # 1 day
|
|
646
|
+
end
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
Cache key inputs include the normalized payload, `iat`, output mode (`json`
|
|
650
|
+
vs URL), and configured domain.
|
|
651
|
+
|
|
652
|
+
TTL behavior:
|
|
653
|
+
|
|
654
|
+
- If `iat` is present: cached for `cache_ttl`
|
|
655
|
+
- If `iat` is omitted: cached for `7 * cache_ttl`
|
|
656
|
+
|
|
191
657
|
### Strip extensions
|
|
192
658
|
|
|
193
659
|
When `strip_extensions` is enabled, the client removes file extensions from the
|
data/lib/og_pilot_ruby/client.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "digest"
|
|
3
4
|
require "json"
|
|
4
5
|
require "logger"
|
|
5
6
|
require "net/http"
|
|
@@ -25,14 +26,24 @@ module OgPilotRuby
|
|
|
25
26
|
params.delete("path") if params.key?("path")
|
|
26
27
|
params[:path] = manual_path.to_s.strip.empty? ? resolved_path(default:) : normalize_path(manual_path)
|
|
27
28
|
|
|
29
|
+
cache_key = cache_key_for(params, iat:, json:)
|
|
30
|
+
if config.cache_store && cache_key
|
|
31
|
+
cached = read_cached(cache_key)
|
|
32
|
+
return cached if cached
|
|
33
|
+
end
|
|
34
|
+
|
|
28
35
|
uri = build_uri(params, iat:)
|
|
29
36
|
response, final_uri = request(uri, json:, headers:)
|
|
30
37
|
|
|
31
|
-
if json
|
|
38
|
+
result = if json
|
|
32
39
|
JSON.parse(response.body)
|
|
33
40
|
else
|
|
34
41
|
response["Location"] || final_uri.to_s
|
|
35
42
|
end
|
|
43
|
+
|
|
44
|
+
write_cached(cache_key, result, iat:) if config.cache_store && cache_key && result
|
|
45
|
+
|
|
46
|
+
result
|
|
36
47
|
rescue StandardError => e
|
|
37
48
|
log_create_image_failure(e, json:)
|
|
38
49
|
json ? { "image_url" => nil } : nil
|
|
@@ -42,6 +53,25 @@ module OgPilotRuby
|
|
|
42
53
|
|
|
43
54
|
attr_reader :config
|
|
44
55
|
|
|
56
|
+
def cache_key_for(params, iat:, json:)
|
|
57
|
+
key_data = params.transform_keys(&:to_sym).merge(iat: iat, json: json, domain: domain!)
|
|
58
|
+
normalized = key_data.sort_by { |k, _| k.to_s }.to_h
|
|
59
|
+
"og_pilot:#{Digest::SHA256.hexdigest(normalized.to_json)[0, 16]}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def read_cached(cache_key)
|
|
63
|
+
config.cache_store.read(cache_key)
|
|
64
|
+
rescue StandardError
|
|
65
|
+
nil
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def write_cached(cache_key, result, iat:)
|
|
69
|
+
ttl = iat ? config.cache_ttl : (7 * config.cache_ttl)
|
|
70
|
+
config.cache_store.write(cache_key, result, expires_in: ttl)
|
|
71
|
+
rescue StandardError
|
|
72
|
+
nil
|
|
73
|
+
end
|
|
74
|
+
|
|
45
75
|
def log_create_image_failure(error, json:)
|
|
46
76
|
mode = json ? "json" : "url"
|
|
47
77
|
message = "OgPilotRuby create_image failed (mode=#{mode}): #{error.class}: #{error.message}"
|
|
@@ -5,7 +5,7 @@ module OgPilotRuby
|
|
|
5
5
|
DEFAULT_BASE_URL = "https://ogpilot.com"
|
|
6
6
|
private_constant :DEFAULT_BASE_URL
|
|
7
7
|
|
|
8
|
-
attr_accessor :api_key, :domain, :base_url, :open_timeout, :read_timeout, :strip_extensions
|
|
8
|
+
attr_accessor :api_key, :domain, :base_url, :open_timeout, :read_timeout, :strip_extensions, :cache_store, :cache_ttl
|
|
9
9
|
|
|
10
10
|
def initialize
|
|
11
11
|
@api_key = ENV.fetch("OG_PILOT_API_KEY", nil)
|
|
@@ -14,6 +14,8 @@ module OgPilotRuby
|
|
|
14
14
|
@open_timeout = 5
|
|
15
15
|
@read_timeout = 10
|
|
16
16
|
@strip_extensions = true
|
|
17
|
+
@cache_store = nil
|
|
18
|
+
@cache_ttl = 86400
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
end
|