8
91. Click `Fork`
102. Change `location` (Line 4) to describe your location. It accepts fairly flexible English descriptions which it turns into locations via [nominatim's geocoder API](https://www.val.town/v/stevekrouse/nominatimSearch).
113. Click `Run`
12
80 // expert: {
81 // type: "string",
82 // description: "The type of expert requested (e.g., 'Private Detective', 'Therapist').",
83 // },
84 // },
9
10 try {
11 const response = await fetch("https://official-joke-api.appspot.com/random_joke");
12 if (!response.ok) {
13 throw new Error("Failed to fetch joke");
85}
86
87export default class VestaboardAPI {
88 private apiKey: string;
89
90 constructor(apiKey: string) {
91 this.apiKey = apiKey;
92 }
93
96 method: "GET",
97 headers: {
98 "X-Vestaboard-Read-Write-Key": this.apiKey,
99 "Content-Type": "application/json",
100 },
102
103 if (!response.ok) {
104 throw new Error(`Vestaboard API error: ${response.status}`);
105 }
106
116 method: "POST",
117 headers: {
118 "X-Vestaboard-Read-Write-Key": this.apiKey,
119 "Content-Type": "application/json",
120 },
123
124 if (!response.ok) {
125 throw new Error(`Vestaboard API error: ${response.status}`);
126 }
127
139
140 if (!response.ok) {
141 throw new Error(`Vestaboard format API error: ${response.status}`);
142 }
143
31Refer to [Twitter's search operators](https://socialdata.gitbook.io/docs/twitter-tweets/retrieve-search-results-by-keyword#endpoint-parameters) to fine-tune your query.
32
33### 4. Test API call
34Set `isProd = false` in the code if you are testing, to ensure there are enough tweets to display. <br>
35Toggle it back to `true` when you're ready to run this cron job in production and actuall send notifications.
60
61### NOTE: Usage Limits
62This val uses the SocialData API for Twitter data:
63
64- **Proxies via Val Town's [SocialDataProxy](https://www.val.town/v/stevekrouse/socialDataProxy)**: Limited to 10 cents per day for [**Val Town Pro users**](https://www.val.town/pricing). This API is *only* for Pro users.
65- **Need more calls?** Sign up for your own [SocialData API token](https://socialdata.tools) and configure the [`socialDataSearch`](https://www.val.town/v/stevekrouse/socialDataSearch) function.
24 - Ensure the token has read/write access to _Contents_ for the repo
25 - Copy the access token and add that as the `GITHUB_TOKEN` env var in this val
261. Add a new [Val Town API token][] with read/write permissions. Add that token to the val's env vars as `VALTOWN_TOKEN`
271. Add a `VAL_SECRET` env var to the val. Use this secret to sign the webhook POST request to the `/push` endpoint. Use this endpoint to commit vals from Val Town to your GitHub repo.
28
68
69- `GITHUB_TOKEN`: Read/write GitHub personal access token for reading and writing repo contents
70- `VALTOWN_TOKEN`: ValTown API token (with read/write Vals permissions) for writing updates from GitHub
71- `GITHUB_WEBHOOK_SECRET`: secret for verifying webhooks from GitHub
72- `VAL_SECRET`: secret for verifying requests to the `/push` endpoint
98[github oauth app]: https://github.com/settings/developers
99[access token]: https://github.com/settings/tokens
100[val town api token]: https://www.val.town/settings/api
101[troubleshooting]: #troubleshooting
102
8
91. Click `Fork`
102. Change `location` (Line 4) to describe your location. It accepts fairly flexible English descriptions which it turns into locations via [nominatim's geocoder API](https://www.val.town/v/stevekrouse/nominatimSearch).
113. Click `Run`
12
3
4const stripe = new Stripe(Deno.env.get("stripe_sk_customer_readonly") as string, {
5 apiVersion: "2020-08-27",
6});
7
19
20- **Frontend:** HTML, CSS, JavaScript
21- **Backend:** Python (Flask or FastAPI)
22- **AI Model:** OpenAI API / Custom NLP Model
23- **Deployment:** Vercel / Streamlit / Hugging Face Spaces
24
7 * Optimisitically types the values we expect in our environment and context:
8 *
9 * - `Bindings` determines env vars, accessed via `c.env.NAME_OF_VAR` in api handlers
10 * - `Variables` determines context vars, accessed via `c.get("NAME_OF_VAR")` in api handlers
11 */
12export type AppType = {