Refactor trending tags history, make it more correct
This commit is contained in:
parent
f8d46cae58
commit
bc3a96eeed
|
@ -3,6 +3,7 @@ import { Conf } from '@/config.ts';
|
||||||
import { z } from '@/deps.ts';
|
import { z } from '@/deps.ts';
|
||||||
import { trends } from '@/trends.ts';
|
import { trends } from '@/trends.ts';
|
||||||
import { Time } from '@/utils.ts';
|
import { Time } from '@/utils.ts';
|
||||||
|
import { stripTime } from '@/utils/time.ts';
|
||||||
|
|
||||||
const limitSchema = z.coerce.number().catch(10).transform((value) => Math.min(Math.max(value, 0), 20));
|
const limitSchema = z.coerce.number().catch(10).transform((value) => Math.min(Math.max(value, 0), 20));
|
||||||
|
|
||||||
|
@ -25,11 +26,11 @@ const trendingTagsController: AppController = (c) => {
|
||||||
url: Conf.local(`/tags/${name}`),
|
url: Conf.local(`/tags/${name}`),
|
||||||
history: [
|
history: [
|
||||||
{
|
{
|
||||||
day: String(Math.floor(now.getTime() / 1000)),
|
day: String(Math.floor(stripTime(now).getTime() / 1000)),
|
||||||
accounts: String(accounts),
|
accounts: String(accounts),
|
||||||
uses: String(uses),
|
uses: String(uses),
|
||||||
},
|
},
|
||||||
...getTagHistoryWithGapsFilled({
|
...trends.getTagHistory({
|
||||||
tag: name,
|
tag: name,
|
||||||
since: lastWeek,
|
since: lastWeek,
|
||||||
until: now,
|
until: now,
|
||||||
|
@ -44,28 +45,4 @@ const trendingTagsController: AppController = (c) => {
|
||||||
})));
|
})));
|
||||||
};
|
};
|
||||||
|
|
||||||
function generateDateRange(since: Date, until: Date): Date[] {
|
|
||||||
const dates = [];
|
|
||||||
|
|
||||||
const sinceDate = new Date(Date.UTC(since.getUTCFullYear(), since.getUTCMonth(), since.getUTCDate() + 1));
|
|
||||||
const untilDate = new Date(Date.UTC(until.getUTCFullYear(), until.getUTCMonth(), until.getUTCDate()));
|
|
||||||
|
|
||||||
while (sinceDate < untilDate) {
|
|
||||||
dates.push(new Date(sinceDate));
|
|
||||||
sinceDate.setUTCDate(sinceDate.getUTCDate() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dates.reverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTagHistoryWithGapsFilled(params: Parameters<typeof trends.getTagHistory>[0]) {
|
|
||||||
const history = trends.getTagHistory(params);
|
|
||||||
const dateRange = generateDateRange(params.since, params.until);
|
|
||||||
|
|
||||||
return dateRange.map((day) => {
|
|
||||||
const data = history.find((item) => item.day.getTime() === day.getTime());
|
|
||||||
return data || { day, accounts: 0, uses: 0 };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { trendingTagsController };
|
export { trendingTagsController };
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Sqlite } from '@/deps.ts';
|
import { Sqlite } from '@/deps.ts';
|
||||||
import { hashtagSchema, hexIdSchema } from '@/schema.ts';
|
import { hashtagSchema, hexIdSchema } from '@/schema.ts';
|
||||||
import { Time } from './utils.ts';
|
import { Time } from '@/utils.ts';
|
||||||
|
import { generateDateRange } from '@/utils/time.ts';
|
||||||
|
|
||||||
interface GetTrendingTagsOpts {
|
interface GetTrendingTagsOpts {
|
||||||
since: Date;
|
since: Date;
|
||||||
|
@ -63,7 +64,7 @@ class TrendsDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTagHistory({ tag, since, until, limit = 7, offset = 0 }: GetTagHistoryOpts) {
|
getTagHistory({ tag, since, until, limit = 7, offset = 0 }: GetTagHistoryOpts) {
|
||||||
return this.#db.query<string[]>(
|
const result = this.#db.query<string[]>(
|
||||||
`
|
`
|
||||||
SELECT date(inserted_at), COUNT(DISTINCT pubkey8), COUNT(*)
|
SELECT date(inserted_at), COUNT(DISTINCT pubkey8), COUNT(*)
|
||||||
FROM tag_usages
|
FROM tag_usages
|
||||||
|
@ -79,6 +80,16 @@ class TrendsDB {
|
||||||
accounts: Number(row[1]),
|
accounts: Number(row[1]),
|
||||||
uses: Number(row[2]),
|
uses: Number(row[2]),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const dateRange = generateDateRange(
|
||||||
|
new Date(since.getTime() + Time.days(1)),
|
||||||
|
new Date(until.getTime() - Time.days(offset)),
|
||||||
|
).reverse();
|
||||||
|
|
||||||
|
return dateRange.map((day) => {
|
||||||
|
const data = result.find((item) => item.day.getTime() === day.getTime());
|
||||||
|
return data || { day, accounts: 0, uses: 0 };
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addTagUsages(pubkey: string, hashtags: string[], date = new Date()): void {
|
addTagUsages(pubkey: string, hashtags: string[], date = new Date()): void {
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { assertEquals } from '@/deps-test.ts';
|
||||||
|
|
||||||
|
import { generateDateRange } from './time.ts';
|
||||||
|
|
||||||
|
Deno.test('generateDateRange', () => {
|
||||||
|
const since = new Date('2023-07-03T16:30:00.000Z');
|
||||||
|
const until = new Date('2023-07-07T09:01:00.000Z');
|
||||||
|
|
||||||
|
const expected = [
|
||||||
|
new Date('2023-07-03T00:00:00.000Z'),
|
||||||
|
new Date('2023-07-04T00:00:00.000Z'),
|
||||||
|
new Date('2023-07-05T00:00:00.000Z'),
|
||||||
|
new Date('2023-07-06T00:00:00.000Z'),
|
||||||
|
new Date('2023-07-07T00:00:00.000Z'),
|
||||||
|
];
|
||||||
|
|
||||||
|
const result = generateDateRange(since, until);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
result.map((d) => d.getTime()),
|
||||||
|
expected.map((d) => d.getTime()),
|
||||||
|
);
|
||||||
|
});
|
|
@ -9,4 +9,24 @@ const Time = {
|
||||||
years: (y: number) => y * Time.days(365),
|
years: (y: number) => y * Time.days(365),
|
||||||
};
|
};
|
||||||
|
|
||||||
export { Time };
|
/** Strips the time off the date, giving 12am UTC. */
|
||||||
|
function stripTime(date: Date): Date {
|
||||||
|
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Strips times off the dates and generates all 24h intervals between them, inclusive of both inputs. */
|
||||||
|
function generateDateRange(since: Date, until: Date): Date[] {
|
||||||
|
const dates = [];
|
||||||
|
|
||||||
|
const sinceDate = stripTime(since);
|
||||||
|
const untilDate = stripTime(until);
|
||||||
|
|
||||||
|
while (sinceDate <= untilDate) {
|
||||||
|
dates.push(new Date(sinceDate));
|
||||||
|
sinceDate.setUTCDate(sinceDate.getUTCDate() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dates;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { generateDateRange, stripTime, Time };
|
||||||
|
|
Loading…
Reference in New Issue