Skip to content

Commit

Permalink
add outright stream schedule (#17)
Browse files Browse the repository at this point in the history
* add outright stream schedule

* fix CI issues
  • Loading branch information
bcheidemann authored Dec 16, 2023
1 parent 86efb7a commit 6fd7555
Show file tree
Hide file tree
Showing 17 changed files with 7,342 additions and 112 deletions.
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
root = true

[*.{ts,tsx,js,jsx}]
indent_style = space
indent_size = 2
1 change: 1 addition & 0 deletions .env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PUBLIC_OUTRIGHT_API=http://outright.api.catlord.co.uk:3001
2 changes: 2 additions & 0 deletions outright-api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
token.json
credentials.json
8 changes: 8 additions & 0 deletions outright-api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
```
bun install
bun run dev
```

```
open http://localhost:3000
```
Binary file added outright-api/bun.lockb
Binary file not shown.
14 changes: 14 additions & 0 deletions outright-api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"scripts": {
"dev": "bun run --hot src/index.ts",
"prod": "bun run src/index.ts"
},
"dependencies": {
"hono": "^3.11.7",
"@google-cloud/local-auth": "2.1.0",
"googleapis": "105"
},
"devDependencies": {
"bun-types": "^1.0.7"
}
}
26 changes: 26 additions & 0 deletions outright-api/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Hono } from "hono";
import { HTTPException } from "hono/http-exception";
import { cors } from "hono/cors";
import { authorize, getSchedule } from "./lib";

const app = new Hono();

app.use("/api/*", cors());

app.get("/api/schedule", async (context) => {
try {
const auth = await authorize();
const schedule = await getSchedule(auth);
return context.json(schedule);
} catch (err) {
console.error(err);
throw new HTTPException(500, {
message: "Error retrieving stream schedule",
});
}
});

export default {
port: 3001,
fetch: app.fetch,
};
84 changes: 84 additions & 0 deletions outright-api/src/lib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import fs from "fs/promises";
import path from "path";
import process from "process";
import { authenticate } from "@google-cloud/local-auth";
import { google } from "googleapis";
import { JSONClient } from "google-auth-library/build/src/auth/googleauth";
import { OAuth2Client } from "google-auth-library/build/src/auth/oauth2client";

const OAUTH_ALLOWED = process.env.OAUTH_ALLOWED === "true";

// If modifying these scopes, delete token.json.
const SCOPES = ["https://www.googleapis.com/auth/spreadsheets.readonly"];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = path.join(process.cwd(), "token.json");
const CREDENTIALS_PATH = path.join(process.cwd(), "credentials.json");

/**
* Reads previously authorized credentials from the save file.
*/
async function loadSavedCredentialsIfExist() {
try {
const content = await fs.readFile(TOKEN_PATH, "utf-8");
const credentials = JSON.parse(content);
return google.auth.fromJSON(credentials);
} catch (err) {
return null;
}
}

/**
* Serializes credentials to a file compatible with GoogleAUth.fromJSON.
*/
async function saveCredentials(client: JSONClient | OAuth2Client) {
const content = await fs.readFile(CREDENTIALS_PATH, "utf-8");
const keys = JSON.parse(content);
const key = keys.installed || keys.web;
const payload = JSON.stringify({
type: "authorized_user",
client_id: key.client_id,
client_secret: key.client_secret,
refresh_token: client.credentials.refresh_token,
});
await fs.writeFile(TOKEN_PATH, payload);
}

/**
* Load or request or authorization to call APIs.
*/
export async function authorize(): Promise<
Parameters<typeof google.sheets>[0]["auth"]
> {
const jsonClient = await loadSavedCredentialsIfExist();
if (jsonClient) {
return jsonClient as OAuth2Client;
} else if (!OAUTH_ALLOWED) {
throw new Error("No saved credentials found and OAUTH_ALLOWED is not set.");
}
const oauthClient = await authenticate({
scopes: SCOPES,
keyfilePath: CREDENTIALS_PATH,
});
if (oauthClient.credentials) {
await saveCredentials(oauthClient);
}
return oauthClient;
}

/**
* Returns the schedule from the spreadsheet.
*/
export async function getSchedule(
auth: Parameters<typeof google.sheets>[0]["auth"]
) {
const sheets = google.sheets({ version: "v4", auth });
const res = await sheets.spreadsheets.values.get({
spreadsheetId: "19NpyiVA9LqIB-F9WPbefJb8crrg_jA3-JMZLnLoC4RE",
range: "SCHEDULE",
});
const rows = res.data.values;

return (rows ?? []) as string[][];
}
9 changes: 9 additions & 0 deletions outright-api/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"esModuleInterop": true,
"strict": true,
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx",
"types": ["bun-types"]
}
}
Loading

0 comments on commit 6fd7555

Please sign in to comment.