Skip to content

Instantly share code, notes, and snippets.

@cowboyd
Created September 12, 2022 15:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cowboyd/a13897e6f8dbffbfb75bdd6a2a4b1eac to your computer and use it in GitHub Desktop.
Save cowboyd/a13897e6f8dbffbfb75bdd6a2a4b1eac to your computer and use it in GitHub Desktop.
import { google } from 'googleapis'
import { Firestore } from '@google-cloud/firestore'
import { main, createQueue } from 'effection';
import "path"
import _ from "lodash"
class DB {
constructor() {
this.firestore = new Firestore()
this.name = "meta/meta";
}
*init() {
const metaDoc = doc(this.firestore, "meta/meta")
let snapshot = yield getDoc(metaDoc)
}
*get(path, id) {
docRef = doc(this.firestore, path, id)
docSnp = yield getDoc(docRef)
return docSnp.exists ? docSnp : null
}
}
function* dereferencePages(data, apiMethod, apiParams) {
while (true) {
if (!("nextPageToken" in data))
break
apiParams.pageToken = response.data.nextPageToken
response = yield apiMethod(apiParams)
data = { ...response.data }
}
}
function* getWithCache(db, apiMethod, apiParams, id) {
let headers = {}
let cache = db.firestore.collection("cache")
let cached_ref = cache.doc("id")
let cached_doc = yield cached_ref.get()
if (cached_doc.exists) {
if (_.get(cached_doc, "videosdb.etag")) {
headers["If-None-Match"] = cached_doc.videosdb.etag
}
}
apiParams.headers = headers
let response = yield apiMethod(apiParams)
let result = null
switch (response.status) {
case 304:
result = {
doc: cached_doc,
modified: false
}
break
default:
let full_data = dereferencePages(response.data, apiMethod, apiParams)
let doc_ref = cache.doc(id)
yield doc_ref.set(full_data.items)
result = {
doc: full_data,
modified: true
}
}
return result
}
class PlaylistRetriever {
constructor(db, api, queue) {
this.db = db
this.queue = queue
this.api = api
}
*start() {
let channel_id = process.env.YOUTUBE_CHANNEL_ID
let params = {
"part": "snippet,contentDetails,statistics",
"id": channel_id
}
console.info("Retrieving channel " + channel_id)
let method = this.api.channels.list.bind(this.api)
let channel_info = yield getWithCache(this.db,
method,
params,
channel_id)
console.debug(channel_info)
this.YT_CHANNEL_NAME = channel_info.snippet.title
let doc = this.db.firestore.doc("channel_infos/" + channel_id)
yield doc.set(channel_info, { merge: true })
let playlist_ids = null
if (process.env.DEBUG) {
let params = {
"part": "contentDetails",
"channelId": channel_id
}
let response = yield this.api.channelSections.list(params)
}
let playlistQueue = createQueue("Playlist queue")
}
}
class Downloader {
constructor(exclude_transcripts = false) {
this.valid_video_ids = []
this.db = new DB()
this.api = google.youtube({
version: 'v3',
auth: process.env.YOUTUBE_API_KEY
})
}
*check_for_new_videos() {
console.info("Sync start")
let retriever = new PlaylistRetriever(this.db, this.api)
yield retriever.start()
console.info("Sync finished")
return true
}
}
main(function* () {
let d = new Downloader()
let result = yield d.check_for_new_videos()
console.info("RESULT: " + result)
});
{
"name": "backend",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"private": true,
"dependencies": {
"@google-cloud/firestore": "^6.0.0",
"effection": "^2.0.4",
"googleapis": "^107.0.0",
"lodash": "^4.17.21",
"slugify": "^1.6.5"
},
"type": "module",
"scripts": {
"start": "node app.js"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment