Docs/Skills and code/src/

src/observations.js

Code72 lines3.2 KBsrc/

import { getDb } from "./db.js";

const db = getDb();

const insertVideoSnapshot = db.prepare(`
  INSERT INTO video_metric_snapshots (
    video_id, observed_at, source, view_count, view_count_text,
    view_count_precision, likes_count, published_at, published_at_text,
    published_at_precision, duration_seconds, duration_precision, category, raw_metadata_json
  ) VALUES (
    @video_id, @observed_at, @source, @view_count, @view_count_text,
    @view_count_precision, @likes_count, @published_at, @published_at_text,
    @published_at_precision, @duration_seconds, @duration_precision, @category, @raw_metadata_json
  )
`);

const insertChannelSnapshot = db.prepare(`
  INSERT INTO channel_metric_snapshots (
    channel_url, observed_at, source, subscriber_count, subscriber_count_text, subscriber_count_precision,
    total_view_count, total_view_count_text, total_view_count_precision, video_count, video_count_text, video_count_precision,
    joined_date, joined_date_text, country, raw_metadata_json
  ) VALUES (
    @channel_url, @observed_at, @source, @subscriber_count, @subscriber_count_text, @subscriber_count_precision,
    @total_view_count, @total_view_count_text, @total_view_count_precision, @video_count, @video_count_text, @video_count_precision,
    @joined_date, @joined_date_text, @country, @raw_metadata_json
  )
`);

export function recordVideoSnapshot(video, source, observedAt = new Date().toISOString()) {
  if (!video?.video_id) return false;
  insertVideoSnapshot.run({
    video_id: video.video_id,
    observed_at: observedAt,
    source: source ?? video.metadata_source ?? "unknown",
    view_count: video.view_count ?? null,
    view_count_text: video.view_count_text ?? null,
    view_count_precision: video.view_count_precision ?? "unknown",
    likes_count: video.likes_count ?? null,
    published_at: video.published_at ?? null,
    published_at_text: video.published_at_text ?? null,
    published_at_precision: video.published_at_precision ?? "unknown",
    duration_seconds: video.duration_seconds ?? null,
    duration_precision: video.duration_precision ?? "unknown",
    category: video.category ?? null,
    raw_metadata_json: video.raw_metadata_json ?? null
  });
  return true;
}

export function recordChannelSnapshot(channel, source, observedAt = new Date().toISOString()) {
  if (!channel?.channel_url) return false;
  insertChannelSnapshot.run({
    channel_url: channel.channel_url,
    observed_at: observedAt,
    source: source ?? channel.metadata_source ?? "unknown",
    subscriber_count: channel.subscriber_count ?? null,
    subscriber_count_text: channel.subscriber_count_text ?? null,
    subscriber_count_precision: channel.subscriber_count_precision ?? "unknown",
    total_view_count: channel.total_view_count ?? null,
    total_view_count_text: channel.total_view_count_text ?? null,
    total_view_count_precision: channel.total_view_count_precision ?? "unknown",
    video_count: channel.video_count ?? null,
    video_count_text: channel.video_count_text ?? null,
    video_count_precision: channel.video_count_precision ?? "unknown",
    joined_date: channel.joined_date ?? null,
    joined_date_text: channel.joined_date_text ?? null,
    country: channel.country ?? null,
    raw_metadata_json: channel.metadata_raw_json ?? null
  });
  return true;
}

Shown as it is in the repository at build time (2026-11-03); the home directory appears as <home>. If this page and the file differ, the file is right. Back to the catalogue.