mirror of
https://github.com/hpware/news-analyze.git
synced 2025-06-23 13:04:23 +00:00
Delete old components from a month ago? & Update draggable window to be using the native svgs by lucide icons & updated the news page to activate the tab changing animation when changing tabs & added caching into the [slug].ts file in publishers/lt & added a basic endpoint for searching for sources.
This commit is contained in:
parent
231a7ce251
commit
8032c3faae
12 changed files with 124 additions and 117 deletions
|
@ -1,5 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useThrottleFn } from "@vueuse/core";
|
import { useThrottleFn } from "@vueuse/core";
|
||||||
|
import { XIcon, MinusIcon } from "lucide-vue-next";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -78,19 +79,23 @@ const stopDrag = () => {
|
||||||
@mousedown="startDrag"
|
@mousedown="startDrag"
|
||||||
class="bg-gray-700 p-2 cursor-move flex justify-between items-center flex-shrink-0 text-white z-[50] selection:opacity-0"
|
class="bg-gray-700 p-2 cursor-move flex justify-between items-center flex-shrink-0 text-white z-[50] selection:opacity-0"
|
||||||
>
|
>
|
||||||
<h3 class="font-semibold text-white">{{ title }}</h3>
|
<h3
|
||||||
|
class="font-semibold text-white selection:opactiy-0 selection:bg-gray-700"
|
||||||
|
>
|
||||||
|
{{ title }}
|
||||||
|
</h3>
|
||||||
<div class="flex flex-row gap-1">
|
<div class="flex flex-row gap-1">
|
||||||
<button
|
<button
|
||||||
@click="emit('min')"
|
@click="emit('min')"
|
||||||
class="p-1 hover:bg-gray-300 dark:hover:bg-gray-600 rounded transition duration-200"
|
class="p-1 hover:bg-gray-300 dark:hover:bg-gray-600 rounded transition duration-200"
|
||||||
>
|
>
|
||||||
━
|
<MinusIcon />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@click="emit('close')"
|
@click="emit('close')"
|
||||||
class="p-1 rounded bg-red-500 text-white hover:bg-red-600 transition duration-200"
|
class="p-1 rounded bg-red-500 text-white hover:bg-red-600 transition duration-200"
|
||||||
>
|
>
|
||||||
✕
|
<XIcon />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -51,6 +51,7 @@ const pullTabsData = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateContent = async (url: string, tabAction: boolean) => {
|
const updateContent = async (url: string, tabAction: boolean) => {
|
||||||
|
contentArray.value = [];
|
||||||
if (tabAction === true) {
|
if (tabAction === true) {
|
||||||
primary.value = url;
|
primary.value = url;
|
||||||
switchTabs.value = true;
|
switchTabs.value = true;
|
||||||
|
|
|
@ -19,7 +19,7 @@ const {
|
||||||
data: source,
|
data: source,
|
||||||
pending,
|
pending,
|
||||||
error,
|
error,
|
||||||
} = await useFetch("/api/cached/getData/fetchSources", {
|
} = await useFetch("/api/publishers/lt_all", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
|
@ -23,21 +23,6 @@ const usersList = await sql`
|
||||||
)
|
)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const createNewsProviders = await sql`
|
|
||||||
create table if not exists newsProviders (
|
|
||||||
uuid text primary key,
|
|
||||||
title text not null,
|
|
||||||
slug text unique,
|
|
||||||
website text not null,
|
|
||||||
description text not null,
|
|
||||||
facebookUrl text,
|
|
||||||
twitterUrl text,
|
|
||||||
threadsUrl text,
|
|
||||||
logoUrl text not null,
|
|
||||||
lean text not null
|
|
||||||
)
|
|
||||||
`;
|
|
||||||
|
|
||||||
const createUserAiChatHistory = await sql`
|
const createUserAiChatHistory = await sql`
|
||||||
CREATE TABLE IF NOT EXISTS chat_history (
|
CREATE TABLE IF NOT EXISTS chat_history (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
|
@ -47,38 +32,7 @@ CREATE TABLE IF NOT EXISTS chat_history (
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
)`;
|
)`;
|
||||||
|
|
||||||
const newsArticles = await sql`
|
const createSources = await sql``;
|
||||||
create table if not exists news_articles (
|
|
||||||
uuid text primary key,
|
|
||||||
title text not null,
|
|
||||||
content text not null,
|
|
||||||
news_org text not null,
|
|
||||||
origin_link text not null,
|
|
||||||
author text,
|
|
||||||
related_uuid text not null
|
|
||||||
)
|
|
||||||
`;
|
|
||||||
|
|
||||||
const hotNews = await sql`
|
|
||||||
create table if not exists hot_news (
|
|
||||||
uuid text primary key,
|
|
||||||
title text not null,
|
|
||||||
news_org text not null,
|
|
||||||
link text not null,
|
|
||||||
related_uuid text not null,
|
|
||||||
created_at timestamptz default current_timestamp
|
|
||||||
)
|
|
||||||
`;
|
|
||||||
|
|
||||||
const articlesLt = await sql`
|
|
||||||
create table if not exists articles_lt (
|
|
||||||
uuid text primary key,
|
|
||||||
title text not null,
|
|
||||||
content text not null,
|
|
||||||
origin text not null,
|
|
||||||
author text
|
|
||||||
)
|
|
||||||
`;
|
|
||||||
|
|
||||||
console.log("Creation Complete");
|
console.log("Creation Complete");
|
||||||
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const slug = getRouterParam(event, "slug");
|
|
||||||
const body = await readBody(event);
|
|
||||||
return {
|
|
||||||
body: body,
|
|
||||||
title: "News Org 1",
|
|
||||||
slug: "taisounds",
|
|
||||||
website: "https://yuanhau.com",
|
|
||||||
description: "wah wah wah wah wah wah I dont fucking care",
|
|
||||||
facebook: "https://www.facebook.csdkc",
|
|
||||||
logoUrl:
|
|
||||||
"https://cdn.discordapp.com/avatars/918723093646684180/4eecc27ac05ee8a701fa167808610c7a.jpg",
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,27 +0,0 @@
|
||||||
import sql from "~/server/components/postgres";
|
|
||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const body = await readBody(event);
|
|
||||||
const query = getQuery(event);
|
|
||||||
/*const sources = await sql`SELECT * FROM sources`;
|
|
||||||
return sources;*/
|
|
||||||
// Fake data
|
|
||||||
return {
|
|
||||||
status: "ok",
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: "Source 1",
|
|
||||||
logo: "#",
|
|
||||||
url: "https://source1.com",
|
|
||||||
description: "Description for Source 1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: "Source 2",
|
|
||||||
logo: "#",
|
|
||||||
url: "https://source2.com",
|
|
||||||
description: "Description for Source 2",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
});
|
|
44
server/api/create_database.ts
Normal file
44
server/api/create_database.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import sql from "~/server/components/postgres";
|
||||||
|
|
||||||
|
const createUsers = await sql`
|
||||||
|
create table if not exists users (
|
||||||
|
uuid text primary key,
|
||||||
|
created_at timestamptz default current_timestamp,
|
||||||
|
username text not null unique,
|
||||||
|
avatarurl text,
|
||||||
|
firstname text,
|
||||||
|
passwordhash text not null,
|
||||||
|
email text
|
||||||
|
);
|
||||||
|
`;
|
||||||
|
|
||||||
|
const usersList = await sql`
|
||||||
|
create table if not exists usertokens (
|
||||||
|
token text not null primary key,
|
||||||
|
created_at timestamptz default current_timestamp,
|
||||||
|
username text not null,
|
||||||
|
email text,
|
||||||
|
avatarurl text,
|
||||||
|
firstname text
|
||||||
|
)
|
||||||
|
`;
|
||||||
|
|
||||||
|
const createUserAiChatHistory = await sql`
|
||||||
|
CREATE TABLE IF NOT EXISTS chat_history (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
uuid VARCHAR(255) NOT NULL,
|
||||||
|
role VARCHAR(50) NOT NULL,
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)`;
|
||||||
|
|
||||||
|
const createSources = await sql``;
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
return {
|
||||||
|
createUsers: createUsers,
|
||||||
|
usersList: usersList,
|
||||||
|
createUserAiChatHistory: createUserAiChatHistory,
|
||||||
|
createSources: createSources,
|
||||||
|
};
|
||||||
|
});
|
|
@ -1,10 +0,0 @@
|
||||||
import s3 from "~/server/components/s3";
|
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const slug = getRouterParam(event, "slug");
|
|
||||||
return sendRedirect(
|
|
||||||
event,
|
|
||||||
`${process.env.S3_ENDPOINT}/${process.env.S3_BUCKETNAME}/${slug}`,
|
|
||||||
302,
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,8 +1,43 @@
|
||||||
// TODO Add caching
|
import sql from "~/server/components/postgres";
|
||||||
|
|
||||||
import * as cheerio from "cheerio";
|
import * as cheerio from "cheerio";
|
||||||
|
|
||||||
|
// Caching
|
||||||
|
|
||||||
|
interface CacheItems {
|
||||||
|
slug: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
articles: any[];
|
||||||
|
timestamp: number;
|
||||||
|
}
|
||||||
|
const CACHE_DURATION = 1000 * 60 * 30;
|
||||||
|
const cache: Record<string, CacheItems> = {};
|
||||||
|
|
||||||
|
function cleanupCache() {
|
||||||
|
const now = Date.now();
|
||||||
|
Object.keys(cache).forEach((key) => {
|
||||||
|
if (now - cache[key].timestamp > CACHE_DURATION) {
|
||||||
|
delete cache[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setInterval(cleanupCache, CACHE_DURATION);
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
const slug = getRouterParam(event, "slug");
|
const slug = getRouterParam(event, "slug");
|
||||||
|
if (!slug) {
|
||||||
|
return {
|
||||||
|
error: "NO_SLUG_PROVIDED",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (cache[slug] && Date.now() - cache[slug].timestamp < CACHE_DURATION) {
|
||||||
|
return {
|
||||||
|
...cache[slug],
|
||||||
|
cached: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
const buildUrl = "https://today.line.me/tw/v3/publisher/" + slug;
|
const buildUrl = "https://today.line.me/tw/v3/publisher/" + slug;
|
||||||
try {
|
try {
|
||||||
const req = await fetch(buildUrl, {
|
const req = await fetch(buildUrl, {
|
||||||
|
@ -25,37 +60,42 @@ export default defineEventHandler(async (event) => {
|
||||||
.text()
|
.text()
|
||||||
.replace(/.css-.*\}/, "");
|
.replace(/.css-.*\}/, "");
|
||||||
const description = html("p.description").text();
|
const description = html("p.description").text();
|
||||||
const logoClue = html("div.editor").contents();
|
|
||||||
const logo =
|
|
||||||
logoClue.find("img").attr("srcset") ||
|
|
||||||
html("div.editor div figure img").attr("src") ||
|
|
||||||
"";
|
|
||||||
const bgImage = html("figure.keyVisual img").attr("srcset") || "";
|
|
||||||
const articles = [];
|
|
||||||
const regexArticleLinks = /[a-zA-Z0-9]{7}/g;
|
const regexArticleLinks = /[a-zA-Z0-9]{7}/g;
|
||||||
const otherArticles = <any[]>[];
|
const otherArticles = <any[]>[];
|
||||||
html("a.ltcp-link").each((i, element) => {
|
html("a.ltcp-link").each((i, element) => {
|
||||||
const articleLink = html(element).attr("href");
|
const articleLink = html(element).attr("href");
|
||||||
const articleTitle = html(element).find("h3.header").text();
|
const articleTitle = html(element).find("h3.header").text();
|
||||||
|
//const image = html(element).find("figure").attr("src");
|
||||||
|
console.log(html(element).find("img"));
|
||||||
|
console.log("----------");
|
||||||
const date = html(element)
|
const date = html(element)
|
||||||
.find("div._articleCard div.css-wqleh6 span")
|
.find("div._articleCard div.css-wqleh6 span")
|
||||||
.text();
|
.text();
|
||||||
if (articleLink && articleTitle) {
|
if (articleLink && articleTitle) {
|
||||||
const articleSlug = articleLink.matchAll(regexArticleLinks);
|
const articleSlug = articleLink
|
||||||
|
.replaceAll("article", "")
|
||||||
|
.match(regexArticleLinks);
|
||||||
otherArticles.push({
|
otherArticles.push({
|
||||||
index: i,
|
index: i,
|
||||||
title: articleTitle,
|
title: articleTitle,
|
||||||
link: articleSlug,
|
link: articleSlug[0],
|
||||||
date: date,
|
date: date,
|
||||||
|
//image: image || "/geterrorassets/noImageLogo.svg",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
cache[slug] = {
|
||||||
|
slug: slug,
|
||||||
|
title: newsOrgName,
|
||||||
|
description: description,
|
||||||
|
articles: otherArticles,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
};
|
||||||
return {
|
return {
|
||||||
title: newsOrgName,
|
title: newsOrgName,
|
||||||
description: description,
|
description: description,
|
||||||
logo: logo,
|
|
||||||
articles: otherArticles,
|
articles: otherArticles,
|
||||||
logoClue: String(logoClue),
|
cached: false,
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
|
17
server/api/publishers/lt_all.ts
Normal file
17
server/api/publishers/lt_all.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import sql from "~/server/components/postgres";
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
try {
|
||||||
|
const fetchDataInSQL = await sql`
|
||||||
|
SELECT * FROM lt_news_org;
|
||||||
|
`;
|
||||||
|
return {
|
||||||
|
data: fetchDataInSQL,
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
return {
|
||||||
|
error: "SERVER_SIDE_ERR",
|
||||||
|
elogs: e.message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,3 +0,0 @@
|
||||||
export default defineEventHandler(async (event) => {
|
|
||||||
return {};
|
|
||||||
});
|
|
Loading…
Add table
Add a link
Reference in a new issue