Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/database/postgres/news.ts
Views: 687
/*1* This file is part of CoCalc: Copyright © 2023 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import {6Channel,7EVENT_CHANNEL,8NewsItem,9NewsPrevNext,10RecentHeadline,11} from "@cocalc/util/types/news";12import { LRUQueryCache } from "./util";1314const C = new LRUQueryCache({ ttl_s: 10 * 60 });1516export function clearCache(): void {17C.clear();18}1920// We exclude hidden and future news items and items from the events channel to keep user's news21// feed clear22const Q_FEED = `23SELECT24id, channel, title, text, url,25extract(epoch from date::timestamp)::integer as date26FROM news27WHERE news.date <= NOW()28AND hide IS NOT TRUE29AND channel != '${EVENT_CHANNEL}'30ORDER BY date DESC31LIMIT 100`;3233export async function getFeedData(): Promise<NewsItem[]> {34return await C.query(Q_FEED);35}3637// ::timestamptz because if your server is not in UTC, it will be converted to UTC38// and the UTC epoch timestamp will be used in the browser client as the basis, adding your TZ offset39const Q_BY_ID = `40SELECT41id, channel, title, text, url, hide, tags,42extract(epoch from date::timestamptz)::INTEGER as date43FROM news44WHERE id = $1`;4546// This is used for editing a news item47export async function getNewsItem(48id: number,49cached = true,50): Promise<NewsItem | null> {51return await C.queryOne<NewsItem>(Q_BY_ID, [id], cached);52}5354const Q_BY_ID_USER = `55SELECT56id, channel, title, text, url, hide, tags, history,57date >= NOW() as future,58extract(epoch from date::timestamptz)::INTEGER as date59FROM news60WHERE id = $1`;6162const Q_NEXT = `63SELECT id, title64FROM news65WHERE date >= (SELECT date FROM news WHERE id = $1)66AND id != $167AND hide IS NOT TRUE68AND date < NOW()69AND channel != '${EVENT_CHANNEL}'70ORDER BY date ASC, id ASC71LIMIT 1`;7273const Q_PREV = `74SELECT id, title75FROM news76WHERE date <= (SELECT date FROM news WHERE id = $1)77AND id != $178AND hide IS NOT TRUE79AND date < NOW()80AND channel != '${EVENT_CHANNEL}'81ORDER BY date DESC, id DESC82LIMIT 1`;8384// This is used for displaying one news item (and next/prev ones) to a user85export async function getNewsItemUserPrevNext(id: number): Promise<{86news: NewsItem | null;87prev: NewsPrevNext | null;88next: NewsPrevNext | null;89}> {90const [news, prev, next] = await Promise.all([91C.queryOne<NewsItem>(Q_BY_ID_USER, [id]),92C.queryOne<NewsPrevNext>(Q_PREV, [id]),93C.queryOne<NewsPrevNext>(Q_NEXT, [id]),94]);95return { news, prev, next };96}9798export async function getNewsItemUser(id: number): Promise<NewsItem | null> {99return await C.queryOne<NewsItem>(Q_BY_ID_USER, [id]);100}101102const Q_INDEX = `103SELECT104id, channel, title, text, url, hide, tags,105date >= NOW() as future,106extract(epoch from date::timestamptz)::INTEGER as date107FROM news108WHERE channel <> '${EVENT_CHANNEL}'109ORDER BY date DESC110LIMIT $1111OFFSET $2`;112113export async function getIndex(114limit: number,115offset: number,116): Promise<NewsItem[]> {117return await C.query(Q_INDEX, [limit, offset]);118}119120// get the most recent news item (excluding events)121const Q_MOST_RECENT = `122SELECT123id, channel, title, tags,124extract(epoch from date::timestamptz)::INTEGER as date125FROM news126WHERE date <= NOW()127AND hide IS NOT TRUE128AND channel != '${EVENT_CHANNEL}'129ORDER BY date DESC130LIMIT 1`;131132export async function getMostRecentNews(): Promise<RecentHeadline | null> {133return await C.queryOne<RecentHeadline>(Q_MOST_RECENT);134}135136const Q_RECENT = `137SELECT138id, channel, title, tags,139extract(epoch from date::timestamptz)::INTEGER as date140FROM news141WHERE date <= NOW()142AND channel != '${EVENT_CHANNEL}'143AND hide IS NOT TRUE144ORDER BY date DESC145LIMIT $1`;146147// of the last n picked by Q_RECENT, select one deterministically different every 10 minutes148export async function getRecentHeadlines(149n: number,150): Promise<RecentHeadline[] | null> {151const headlines = await C.query(Q_RECENT, [n]);152if (headlines.length === 0) return null;153return headlines;154}155156// Query upcoming events from a particular channel157const Q_UPCOMING_NEWS_CHANNEL_ITEMS = `158SELECT159id, channel, title, text, url, tags,160extract(epoch from date::timestamp)::integer as date161FROM news162WHERE date >= NOW()163AND channel = $1164AND hide IS NOT TRUE165ORDER BY date166LIMIT 100`;167168export async function getUpcomingNewsChannelItems(169channel: Channel,170): Promise<NewsItem[]> {171return await C.query(Q_UPCOMING_NEWS_CHANNEL_ITEMS, [channel]);172}173174// Query past events from a particular channel175const Q_PAST_NEWS_CHANNEL_ITEMS = `176SELECT177id, channel, title, text, url, tags,178extract(epoch from date::timestamp)::integer as date179FROM news180WHERE date <= NOW()181AND channel = $1182AND hide IS NOT TRUE183ORDER BY date DESC184LIMIT 100`;185186export async function getPastNewsChannelItems(187channel: Channel,188): Promise<NewsItem[]> {189return await C.query(Q_PAST_NEWS_CHANNEL_ITEMS, [channel]);190}191192193