4import { currency } from "https://esm.town/v/stevekrouse/currency";
5
6export async function btcPriceAlert() {
7 const lastBtcPrice: number = await blob.getJSON("lastBtcPrice");
8 let btcPrice = await currency("usd", "btc");
2import { easyAQI } from "https://esm.town/v/stevekrouse/easyAQI?v=5";
3
4export async function aqi(interval: Interval) {
5 const location = "region Hannover "; // <-- change to place, city, or zip code
6 const data = await easyAQI({ location });
1export function replyJSON(data: any, status: number) {
2 return new Response(JSON.stringify(data), {
3 status,
6}
7
8export function replyText(data: string, status: number) {
9 return new Response(data, {
10 status,
13}
14
15export function opNotFoundError(opName: string) {
16 return {
17 ok: false,
21 };
22}
23function formatGetBody(url: string, info: ExtInfo) {
24 const { ns = "?", title = "?" } = info ?? {};
25 return `# ${title} (${ns})
44type HandleRequestFn = (info: any) => Promise<any>;
45
46export function makeExtServer(getInfo: GetInfoFn, handleRequest: HandleRequestFn) {
47 return async (req: Request) => {
48 if (req.method === "GET") {
1import { fetchJSON } from "https://esm.town/v/stevekrouse/fetchJSON";
2
3export async function socialDataSearch(query: string): Promise<SocialDataResponse> {
4 const url = new URL("https://stevekrouse-socialdataproxy.web.val.run/twitter/search");
5 url.searchParams.set("query", query);
8type User = { id: string; username: string; tier: string };
9
10function SimpleLineChart({ data, width = 800, height = 400, margin = { top: 20, right: 20, bottom: 30, left: 40 } }) {
11 const chartWidth = width - margin.left - margin.right;
12 const chartHeight = height - margin.top - margin.bottom;
69}
70
71function Dashboard({ data }) {
72 const chartData = Object.keys(data[0].users).map(username => ({
73 name: username,
106}
107
108function App({ initialData }) {
109 const [data] = useState(initialData);
110
112}
113
114function client() {
115 const initialData = (window as any).INITIAL_DATA;
116 createRoot(document.getElementById("root")).render(<App initialData={initialData} />);
121}
122
123async function getUsageData() {
124 const { sqlite } = await import("https://esm.town/v/stevekrouse/sqlite");
125 const result = await sqlite.execute(`
141}
142
143export default async function server(req: Request): Promise<Response> {
144 const url = new URL(req.url);
145
1A proxy that lets Val Town users get some free [SocialData](https://socialdata.tools) Search to power their Twitter Alerts, ie @stevekrouse/twitterAlert
2
3I reccomend interfacing with this proxy via this helper function: @stevekrouse/socialDataSearch
15type UsageData = { username: string; usage_count: number; date: string };
16
17function UsageDashboard() {
18 const [usageData, setUsageData] = useState<UsageData[]>([]);
19
20 useEffect(() => {
21 async function fetchUsageData() {
22 const response = await fetch('/usage-data');
23 const data = await response.json();
85}
86
87function client() {
88 createRoot(document.getElementById("root")).render(<UsageDashboard />);
89}
90if (typeof document !== "undefined") { client(); }
91
92export default async function(req: Request): Promise<Response> {
93 const url = new URL(req.url);
94
1A proxy that lets Val Town users get some free [SocialData](https://socialdata.tools) Search to power their Twitter Alerts, ie @stevekrouse/twitterAlert
2
3I reccomend interfacing with this proxy via this helper function: @stevekrouse/socialDataSearch
60});
61
62export default async function server(req: Request): Promise<Response> {
63 return app.fetch(req);
64}
33- [x] fix wonky sidebar separator height problem (thanks to @stevekrouse)
34- [x] make result tables scrollable
35- [x] add export to CSV, and JSON (CSV and JSON helper functions written in [this val](https://www.val.town/v/nbbaier/sqliteExportHelpers). Thanks to @pomdtr for merging the initial version!)
36- [x] add listener for cmd+enter to submit query
A helper function to build a file's email
Simple functional CSS library for Val Town
LangChain (https://langchain.com) Ambassador, KubeSphere (https://kubesphere.io) Ambassador, CNCF OpenFunction (https://openfunction.dev) TOC Member.
import { OpenAI } from "https://esm.town/v/std/openai";
export default async function(req: Request): Promise<Response> {
if (req.method === "OPTIONS") {
return new Response(null, {
headers: {
"Access-Control-Allow-Origin": "*",