Compare commits

..

No commits in common. "41e12eb42bedb4a5df5d19376a6843a6950b4497" and "b716a0ed5c2816d76a434ad3fdc66287971b5b2b" have entirely different histories.

9 changed files with 122 additions and 141 deletions

View File

@ -16,16 +16,21 @@
"@nuxtjs/tailwindcss": "6.14.0",
"@sentry/nuxt": "^9",
"@tailwindcss/vite": "^4.1.5",
"@uploadthing/nuxt": "^7.1.7",
"@vueuse/core": "^13.2.0",
"animate.css": "^4.1.1",
"argon2": "^0.43.0",
"axios": "^1.9.0",
"bootstrap-icons": "^1.12.1",
"cheerio": "^1.0.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"crypto-js": "^4.2.0",
"emoji-js": "^3.8.1",
"groq-sdk": "^0.21.0",
"gsap": "^3.13.0",
"html-to-json-parser": "^2.0.1",
"jssoup": "^0.0.15",
"lucide-vue-next": "^0.508.0",
"motion-v": "^1.1.0-alpha.1",
"nuxt": "^3.17.2",
@ -40,6 +45,7 @@
"tailwindcss": "3",
"tailwindcss-animate": "^1.0.7",
"tailwindcss-animatecss": "^3.0.5",
"uploadthing": "^7.6.0",
"uuid": "^11.1.0",
"vue": "^3.5.13",
"vue-router": "^4.5.1",
@ -805,8 +811,12 @@
"@uploadthing/mime-types": ["@uploadthing/mime-types@0.3.5", "", {}, "sha512-iYOmod80XXOSe4NVvaUG9FsS91YGPUaJMTBj52Nwu0G2aTzEN6Xcl0mG1rWqXJ4NUH8MzjVqg+tQND5TPkJWhg=="],
"@uploadthing/nuxt": ["@uploadthing/nuxt@7.1.8", "", { "dependencies": { "@nuxt/kit": "^3.15.0", "@uploadthing/vue": "7.3.1", "defu": "^6.1.4" }, "peerDependencies": { "uploadthing": "^7.2.0" } }, "sha512-l4wa+egG+cVMCcwD9Msjrupf7a+3wvtgm0hU0pUf3c7MM94Vq3LAqOn67rmNR1nnOzpWjula85d3ALNm9so6zQ=="],
"@uploadthing/shared": ["@uploadthing/shared@7.1.8", "", { "dependencies": { "@uploadthing/mime-types": "0.3.5", "effect": "3.14.21", "sqids": "^0.3.0" } }, "sha512-OA9ZrTfILOCt1G93wOD7dZmS653z99Nr3isZpIxzBO3y4B2geKFmPjJUZClig2RrAWLKr2VUYToXKfd9D/wP9w=="],
"@uploadthing/vue": ["@uploadthing/vue@7.3.1", "", { "dependencies": { "@uploadthing/shared": "7.1.8", "@vueuse/core": "^10.9.0", "file-selector": "0.6.0" }, "peerDependencies": { "uploadthing": "^7.2.0", "vue": "^3.4.0" } }, "sha512-1EuNFJ/HBsculzbgNmy380ktyxm/jRlzSGCspIHPXKB2ippyCbograDYuOPBp1jkqHhHHJ9v0NRCq+A+NSx6dg=="],
"@vercel/nft": ["@vercel/nft@0.27.10", "", { "dependencies": { "@mapbox/node-pre-gyp": "^2.0.0-rc.0", "@rollup/pluginutils": "^5.1.3", "acorn": "^8.6.0", "acorn-import-attributes": "^1.9.5", "async-sema": "^3.1.1", "bindings": "^1.4.0", "estree-walker": "2.0.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "node-gyp-build": "^4.2.2", "picomatch": "^4.0.2", "resolve-from": "^5.0.0" }, "bin": { "nft": "out/cli.js" } }, "sha512-zbaF9Wp/NsZtKLE4uVmL3FyfFwlpDyuymQM1kPbeT0mVOHKDQQNjnnfslB3REg3oZprmNFJuh3pkHBk2qAaizg=="],
"@vitejs/plugin-vue": ["@vitejs/plugin-vue@5.2.4", "", { "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA=="],
@ -957,6 +967,8 @@
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
"bootstrap-icons": ["bootstrap-icons@1.13.1", "", {}, "sha512-ijombt4v6bv5CLeXvRWKy7CuM3TRTuPEuGaGKvTV5cz65rQSY8RQ2JcHt6b90cBBAC7s8fsf2EkQDldzCoXUjw=="],
"brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
@ -1219,6 +1231,10 @@
"electron-to-chromium": ["electron-to-chromium@1.5.161", "", {}, "sha512-hwtetwfKNZo/UlwHIVBlKZVdy7o8bIZxxKs0Mv/ROPiQQQmDgdm5a+KvKtBsxM8ZjFzTaCeLoodZ8jiBE3o9rA=="],
"emoji-datasource": ["emoji-datasource@15.0.1", "", {}, "sha512-aF5Q6LCKXzJzpG4K0ETiItuzz0xLYxNexR9qWw45/shuuEDWZkOIbeGHA23uopOSYA/LmeZIXIFsySCx+YKg2g=="],
"emoji-js": ["emoji-js@3.8.1", "", { "dependencies": { "emoji-datasource": "15.0.1" } }, "sha512-yyXMnZLXgqQHAhEm2DKK4Nrca+jbLQfNOP2mLcNTS6XxzzbQLDFHAguPQrtJS4Udot0Pvomwmh1ckQzhrePhKw=="],
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"emoji-regex-xs": ["emoji-regex-xs@2.0.1", "", {}, "sha512-1QFuh8l7LqUcKe24LsPUNzjrzJQ7pgRwp1QMcZ5MX6mFplk2zQ08NVCM84++1cveaUUYtcCYHmeFEuNg16sU4g=="],
@ -1327,6 +1343,8 @@
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
"file-selector": ["file-selector@0.6.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw=="],
"file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
@ -1451,6 +1469,8 @@
"html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
"htmlparser": ["htmlparser@1.7.7", "", {}, "sha512-zpK66ifkT0fauyFh2Mulrq4AqGTucxGtOhZ8OjkbSfcCpkqQEI8qRkY0tSQSJNAQ4HUZkgWaU4fK4EH6SVH9PQ=="],
"htmlparser2": ["htmlparser2@9.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.1.0", "entities": "^4.5.0" } }, "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ=="],
"http-assert": ["http-assert@1.5.0", "", { "dependencies": { "deep-equal": "~1.0.1", "http-errors": "~1.8.0" } }, "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w=="],
@ -1575,6 +1595,8 @@
"jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="],
"jssoup": ["jssoup@0.0.15", "", { "dependencies": { "htmlparser": "^1.7.7" } }, "sha512-9/7qzZQ878Jey0JyNTuy1NYE8Y4G5PbpWQ5hS8vlBD2Ar4MKJNMQ0239yjb+WExRNLiYPSgZSVLyFUwQNWa1ag=="],
"junk": ["junk@4.0.1", "", {}, "sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ=="],
"jwt-decode": ["jwt-decode@4.0.0", "", {}, "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA=="],
@ -2661,6 +2683,8 @@
"@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="],
"@uploadthing/vue/@vueuse/core": ["@vueuse/core@10.11.1", "", { "dependencies": { "@types/web-bluetooth": "^0.0.20", "@vueuse/metadata": "10.11.1", "@vueuse/shared": "10.11.1", "vue-demi": ">=0.14.8" } }, "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww=="],
"@vercel/nft/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
"@vercel/nft/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
@ -3041,6 +3065,12 @@
"@sentry/vite-plugin/unplugin/webpack-virtual-modules": ["webpack-virtual-modules@0.5.0", "", {}, "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw=="],
"@uploadthing/vue/@vueuse/core/@types/web-bluetooth": ["@types/web-bluetooth@0.0.20", "", {}, "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="],
"@uploadthing/vue/@vueuse/core/@vueuse/metadata": ["@vueuse/metadata@10.11.1", "", {}, "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw=="],
"@uploadthing/vue/@vueuse/core/@vueuse/shared": ["@vueuse/shared@10.11.1", "", { "dependencies": { "vue-demi": ">=0.14.8" } }, "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA=="],
"@vercel/nft/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"@vueuse/integrations/@vueuse/core/@vueuse/metadata": ["@vueuse/metadata@12.8.2", "", {}, "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A=="],

View File

@ -23,6 +23,7 @@ const emit = defineEmits([
"openNewsSourcePage",
"windowopener",
]);
const staticid = computed(() => props.staticid);
const openNewWindow = (itemId: string) => {
emit("windowopener", "aboutNewsOrg");
@ -284,7 +285,10 @@ const openPublisher = (text: string) => {
<div>
<div>
<h3 class="text-lg">類似文章</h3>
<div class="space-y-2">
<div
class="space-y-2"
>
<div
v-for="similar in useArgFindRel(item.title, item.publisher)"
:key="similar.item.id"
@ -298,12 +302,8 @@ const openPublisher = (text: string) => {
</div>
</div>
</div>
<div
v-if="checkIfEmpty(item.title)"
class="text-gray-500 text-sm"
>
找不到類似文章
</div>
<div v-if="checkIfEmpty(item.title)" class="text-gray-500 text-sm">找不到類似文章</div>
</div>
<!--<div v-for="item in findRel(item.title)">
{{ item }}

View File

@ -1,32 +1,13 @@
<script setup lang="ts">
const user = ref();
const userToken = localStorage.getItem("token");
const { t, locale } = useI18n();
onMounted(async () => {
const req = await fetch("/api/user/validateUserToken", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
token: userToken,
lang: locale,
page: "settings",
}),
});
const res = req.json();
user.value = res;
});
const logoutAction = () => {
const logoutAction = () => {};
}
</script>
<template>
<div class="justify-center align-center text-center">
<div class="">Greetings, {{ user }}</div>
<div class="bg-gray-200/70 p-2 m-2 w-full">
<div>
<div class="bg-gray-400 p-2 m-2 w-full">
<button @click="logoutAction">Logout</button>
</div>
<hr/>
<div class="justiy-center align-center text-center">Settings v0.0.1</div>
</div>
</template>

View File

@ -1,6 +1,6 @@
<script setup lang="ts">
// Imports
const { t, locale } = useI18n();
const { t } = useI18n();
// Values
const allowed = ref(false);
const error = ref(false);
@ -9,21 +9,7 @@ const emit = defineEmits(["windowopener", "error", "loadValue"]);
try {
// await :(
const token = localStorage.getItem("token");
const { data, error: sendError } = await useFetch(
"/api/user/validateUserToken",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
token: token,
lang: locale,
page: "a_window_application_using_blurPageBeforeLogin_component",
}),
},
);
const { data, error: sendError } = await useFetch("/api/user/checkcookie");
if (sendError.value) {
error.value = true;
}

View File

@ -29,16 +29,21 @@
"@nuxtjs/tailwindcss": "6.14.0",
"@sentry/nuxt": "^9",
"@tailwindcss/vite": "^4.1.5",
"@uploadthing/nuxt": "^7.1.7",
"@vueuse/core": "^13.2.0",
"animate.css": "^4.1.1",
"argon2": "^0.43.0",
"axios": "^1.9.0",
"bootstrap-icons": "^1.12.1",
"cheerio": "^1.0.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"crypto-js": "^4.2.0",
"emoji-js": "^3.8.1",
"groq-sdk": "^0.21.0",
"gsap": "^3.13.0",
"html-to-json-parser": "^2.0.1",
"jssoup": "^0.0.15",
"lucide-vue-next": "^0.508.0",
"motion-v": "^1.1.0-alpha.1",
"nuxt": "^3.17.2",
@ -53,6 +58,7 @@
"tailwindcss": "3",
"tailwindcss-animate": "^1.0.7",
"tailwindcss-animatecss": "^3.0.5",
"uploadthing": "^7.6.0",
"uuid": "^11.1.0",
"vue": "^3.5.13",
"vue-router": "^4.5.1"

View File

@ -1,55 +1,10 @@
<script setup lang="ts">
const apis = [
{
apiroute: "/shortforward",
name: "A Simple url forwarder.",
content:
"This is maly used for yhw.tw/news, which is a super simple redirection tool for easy redirecting.",
caching: false,
},
{
apiroute: "/api/tabs",
name: "Get LINE Today Tabs",
content: "Using LINE Today as a source for getting tabs & caching results.",
caching: true,
},
{
apiroute: "/api/home/lt",
name: "Get the news feed of LINE Today",
content:
"This endpoint requires ?query=, and you can go the the /api/tabs to find the query.",
caching: true,
},
{
apiroute: "/api/news/get/lt/[slug]",
name: "Get the news article using node-fetch & cheerio",
content:
"This endpoint requires the slug to be filled in, in order to get it to work.",
caching: true,
},
{
apiroute: "/api/ai/chat/[slug]",
name: "",
content: "",
caching: false,
},
{
apiroute: "/api/ai/summarize/[slug]",
name: "",
content: "",
caching: false,
},
];
</script>
<template>
<div
class="justify-center align-center text-center absolute inset-0 flex flex-col"
>
<h1 class="text-4xl text-bold">APIs</h1>
<div class="items flex flex-row flex-wrap">
<div class="item group" v-for="item in apis">
{{ item.name }}
</div>
<div class="item group"></div>
</div>
</div>
</template>

View File

@ -472,6 +472,12 @@ const openNewsSourcePage = async (slug: string, titleName: string) => {
passedValues.value = null;
}, 1000);
};
// Not used?
const getStaticArticleId = () => {
storeStaticArticleId.value += 1;
return storeStaticArticleId.value;
};
</script>
<template>
<div v-if="changeLangAnimation">
@ -591,6 +597,7 @@ const openNewsSourcePage = async (slug: string, titleName: string) => {
@loadValue=""
@openArticles="openArticles"
@openNewsSourcePage="openNewsSourcePage"
:staticid="getStaticArticleId"
:values="passedValues"
/>
</Suspense>

View File

@ -0,0 +1,64 @@
// This should be hooked up to a database soon.
import sql from "~/server/components/postgres";
// Parse Date Function
function checkDate(dateString: string) {
const now = new Date();
const parsed = new Date(dateString);
const timer = 60 * 60 * 1;
return now.getTime() - parsed.getTime() > timer;
}
export default defineEventHandler(async (event) => {
const loginCookie = getCookie(event, "session");
const lastCheckCookie = getCookie(event, "last_check");
const nowDate = new Date().toLocaleString();
console.log(nowDate);
if (!lastCheckCookie && loginCookie) {
deleteCookie(event, "session");
setCookie(event, "lastCheckCookie", nowDate, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
path: "/",
});
return {
auth: false,
user: null,
};
}
if (!lastCheckCookie) {
setCookie(event, "lastCheckCookie", nowDate, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
path: "/",
});
}
if (checkDate(String(lastCheckCookie))) {
setCookie(event, "lastCheckCookie", nowDate, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
path: "/",
});
}
if (!loginCookie) {
setCookie(event, "lastCheckCookie", nowDate, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
path: "/",
});
return {
auth: false,
user: null,
};
}
const loginCookieStore = atob(loginCookie);
/*const findUser = sql`
select * from userlogintokens
where token = ${loginCookieStore}
`;*/
return {
auth: true,
user: "testing",
loginCookie: loginCookieStore, // Debug
};
});

View File

@ -1,48 +0,0 @@
import sql from "~/server/components/postgres";
export default defineEventHandler(async (event) => {
const body = await readBody(event);
const token = body.token;
if (!token) {
return {
error: "NO_TOKEN_GIVEN",
requested_action: "SHOW_WARNING",
};
}
const checkIsUUIDRegex =
/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/;
if (!checkIsUUIDRegex.test(token)) {
return {
error: "NOT_A_UUID",
requested_action: "LOGOUT_USER",
};
}
const fetchViaSQL = await sql`
SELECT * FROM usertokens
where token=${token}
`;
if (!fetchViaSQL[0]) {
return {
error: "INVALID_TOKEN",
requested_action: "LOGOUT_USER",
};
}
const tokenDate = new Date(fetchViaSQL[0].created_at);
const now = new Date();
const dayInMilliseconds = 24 * 60 * 60 * 1000;
if (now.getTime() - tokenDate.getTime() > dayInMilliseconds) {
return {
error: "TOKEN_EXPIRED",
requested_action: "LOGOUT_USER",
};
}
return {
userAccount: fetchViaSQL[0].username,
requested_action: "CONTINUE",
email: fetchViaSQL[0].email,
avatarURL: fetchViaSQL[0].avatarurl,
firstName: fetchViaSQL[0].firstName,
};
});