diff --git a/.env.example b/.env.example index c597a30..3f7ebaa 100644 --- a/.env.example +++ b/.env.example @@ -1,28 +1,12 @@ # Please use .env.exmaple as an starting point. Rename it to .env and fill in the values, the application requrires it. # This is the default .env file. - -# S3 INFO -S3_ACCESS_KEY="" -S3_SECRET_KEY="" -S3_BUCKETNAME="" -S3_ENDPOINT="" - -# GITHUB OAUTH (NOT WORKING 4n) -NUXT_GITHUB_CLIENT_ID="" -NUXT_GITHUB_CLIENT_SECRET="" - # GLOBAL DATABASE POSTGRES_URL="" +# THE BELOW TWO IS NOW IN THE DB, PLEASE FOLOW THIS GUIDE: https://github.com/hpware/news-analyze?tab=readme-ov-file#notes # GROQ API KEY -GROQ_API_KEY="" +#GROQ_API_KEY="" # PASSWORD SALT -PASSWORD_HASH_SALT="" - -# CF TURNSTILE -NUXT_CF_TURNSTILE_SITE_KEY="" -NUXT_CF_TURNSTILE_SECRET_KEY="" - -NUXT_DEV_ENV=false +#PASSWORD_HASH_SALT="" diff --git a/README.md b/README.md index 605e7d8..f471953 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,20 @@ Beta (Beta Docker Image): https://newsbeta.20090526.xyz https://github.com/user-attachments/assets/29414c5d-3b2f-420d-93c0-95c14a15bbb7 +## Notes: +The enviroment vars are stored in the database, which is cursed, I know, but this is the only way to let the system access new envs sent by the user, so if you are trying to spin up a instence of this app you MUST put the postgres url in the .env & create a table using beekeeper studio (my choice for SQL editing, you can choose whatever you like), and after that you can create the entire database by using this api call, https://<>/api/create_database in your browser. +```sql + CREATE TABLE IF NOT EXISTS global_vars ( + NAME TEXT PRIMARY KEY NOT NULL, + VAR TEXT NOT NULL + ); + INSERT INTO global_vars(name, var) + VALUES ('groq_api_key', '<>'); + INSERT INTO global_vars(name, var) + VALUES ('password_hash_salt', '<>'); +``` +Replace `<>` with your actual api key, and also replace `<>` with a random salt you get by running this command on your Mac/Linux device (Windows idk) `openssl rand -base64 48`. + ## Issues: ### Onboarding: Onboarding is a must for most people that are using the app for the first time, but I want to do to via a non-video like system, however implementing the function in a already large repo is kinda hard. So later this week, I will just add a basic video onboarding system. @@ -61,13 +75,10 @@ This code is absolutly NOT designed to be spinned up at Vercel or Netlify, it ha ### The API returning outdated data from more than 5+ years: Here is the GitHub Issue: https://github.com/hpware/news-analyze/issues/2 -### Groq API not loading to .env for some reasons. -If the user did not load a GROQ api, the summerizing system will just fail outright. Fixing this rn. - ### When using the desktop in the dev env it pops up an error ![](/.github/README/error1.png) -For some reasons, Nuxt's dev env prev does not display this error, but with the newer ones, it started displaying this error, please run `./wipedev.sh` or `./wipedev.bat` and restart the dev server. (And this is only a temp fix, I have no idea how can I fix this, if you have a fix, please submit a PR thx.) +For some reasons, Nuxt's dev env prev does not display this error, but with the newer ones, it started displaying this error, please run `./wipedev.sh` or `./wipedev.bat` and restart the dev server. (And this is only a temp fix, I have no idea how can I fix this, if you have a fix, please submit a PR, thx.) ## Why? diff --git a/components/app/windows/chatbot.vue b/components/app/windows/chatbot.vue deleted file mode 100644 index 37c0edc..0000000 --- a/components/app/windows/chatbot.vue +++ /dev/null @@ -1,224 +0,0 @@ - - diff --git a/components/app/windows/news.vue b/components/app/windows/news.vue index 265f222..24044c7 100644 --- a/components/app/windows/news.vue +++ b/components/app/windows/news.vue @@ -53,7 +53,7 @@ const contentArray = ref([]); const errorr = ref(false); const switchTabs = ref(false); const tabs = ref([]); -const primary = ref("domestic"); // Hard code default value as top is just pure garbage. +const primary = ref("top"); // This will be later overwritten, so values set here will be useless. const canNotLoadTabUI = ref(false); const isDataCached = ref(false); const pullTabsData = async () => { diff --git a/components/app/windows/newsView.vue b/components/app/windows/newsView.vue index 5d73be8..c1af880 100644 --- a/components/app/windows/newsView.vue +++ b/components/app/windows/newsView.vue @@ -117,7 +117,7 @@ const starArticle = async () => { }; onMounted(async () => { - const req = await fetch(`/user/${slug}/star`); + const req = await fetch(`/api/user/${slug}/star`); const res = await req.json(); staredStatus.value = res; }); @@ -164,7 +164,7 @@ onMounted(async () => { class="justify-center align-center text-center flex flex-col md:flex-row flex-wrap" >
-
+

{{ displayTranslatedText @@ -212,16 +212,6 @@ onMounted(async () => {
{{ summaryText }}

- - -

-
- - -
-
{{ t("app.settings") }} v0.0.3 || Version: {{ getVersionTag() }}
diff --git a/components/app/windows/tos.vue b/components/app/windows/tos.vue deleted file mode 100644 index d5b8323..0000000 --- a/components/app/windows/tos.vue +++ /dev/null @@ -1,9 +0,0 @@ - - diff --git a/components/app/windows/user.vue b/components/app/windows/user.vue deleted file mode 100644 index bac6dd6..0000000 --- a/components/app/windows/user.vue +++ /dev/null @@ -1,78 +0,0 @@ - - diff --git a/i18n/locales/en.json b/i18n/locales/en.json index a007ac0..dd61c67 100644 --- a/i18n/locales/en.json +++ b/i18n/locales/en.json @@ -45,11 +45,11 @@ "apis": "APIs" }, "description": { - "find": "You can easily find the same topic from different news sources.", - "interface": "Use a desktop like interface, the one that you already got used to.", - "documentation": "We provide a documentation for you to learn how to use the app.", - "opensource": "This platform is open source! minus the database part, but I'm going to try!", - "apis": "We use api's that are made via reverse engineering." + "find": "You can find the same topic from different news sources.", + "interface": "This platform uses a desktop like interface, the one that you already got used to.", + "documentation": "We provide a video for you to learn how to use the basics of the application.", + "opensource": "This platform is open source!", + "apis": "We use api's that are made via reverse engineering, here https://github.com/hpware/reverse_engineering" } } }, @@ -116,16 +116,6 @@ "noadlinetoday": "Provides free, no ads Line today." } }, - "pages": { - "privacypolicy": { - "title": "Privacy Policy", - "content": "Ummmm" - }, - "tos": { - "title": "Terms of service", - "content": "N/A" - } - }, "about": { "why": "Why make this website?", "bulletpoints": { diff --git a/i18n/locales/zh-tw.json b/i18n/locales/zh-tw.json index 963ab15..3f98296 100644 --- a/i18n/locales/zh-tw.json +++ b/i18n/locales/zh-tw.json @@ -48,7 +48,7 @@ "find": "你可以輕鬆地從不同的新聞來源找到相同的主題。", "interface": "這個網站使用類似 Xfce / MacOS / DSM 的介面,讓你可以簡單使用這個網站。", "documentation": "我做了一組教學,讓你可以學會如何使用這個網站 UI。", - "opensource": "這個平台的所有程式碼都放在Github上,沒有開源的資料庫,我會想辦法把它用其他方式開源!", + "opensource": "這個平台的所有程式碼都放在Github上!", "apis": "我們使用LINE Today 的資訊來做出一個 API。" } } diff --git a/pages/desktop.vue b/pages/desktop.vue index 3243e06..a5c7e1c 100644 --- a/pages/desktop.vue +++ b/pages/desktop.vue @@ -51,18 +51,14 @@ import translate from "translate"; import checkAppVersion from "~/components/checkAppVersion"; // Import Windows -import UserWindow from "~/components/app/windows/user.vue"; import SourcesWindow from "~/components/app/windows/sources.vue"; import AboutWindow from "~/components/app/windows/about.vue"; -import ChatbotWindow from "~/components/app/windows/chatbot.vue"; import AboutNewsOrgWindow from "~/components/app/windows/aboutNewsOrg.vue"; import TTYWindow from "~/components/app/windows/tty.vue"; import FavStaredWindow from "~/components/app/windows/fav.vue"; import NewsWindow from "~/components/app/windows/news.vue"; import NewsViewWindow from "~/components/app/windows/newsView.vue"; import SettingsWindow from "~/components/app/windows/settings.vue"; -import PrivacyPolicyWindow from "~/components/app/windows/privacypolicy.vue"; -import TOSWindow from "~/components/app/windows/tos.vue"; import onBoardingWindow from "~/components/app/windows/onBoarding.vue"; // Import Icons @@ -83,14 +79,12 @@ const route = useRoute(); // values const popMessage = ref(null); const menuOpen = ref(false); -2; const currentNavBar = ref([]); const bootingAnimation = ref(true); const activeWindows = ref([]); const hiddenWindows = ref([]); const openApp = ref(); const openAppId = ref(); -const openAppNameQuery = ref(); const currentOpenAppId = ref(0); const progress = ref(0); const titleAppName = ref("Desktop"); @@ -101,7 +95,6 @@ const changeLangAnimation = ref(false); const applyForTranslation = ref(false); const langPrefDifferent = ref(false); const notLoggedInState = ref(false); -const translateProvider = ref(""); const newUpdate = ref(false); // Key Data @@ -109,7 +102,6 @@ const menuItems = [ { name: t("app.news"), windowName: "news" }, { name: t("app.sources"), windowName: "sources" }, { name: t("app.starred"), windowName: "starred" }, - { name: t("app.chatbot"), windowName: "chatbot" }, { name: t("app.about"), windowName: "about" }, { name: t("app.terminal"), windowName: "tty" }, { name: t("app.settings"), windowName: "settings" }, @@ -117,13 +109,6 @@ const menuItems = [ ]; const associAppWindow = [ - { - name: "login", - id: "2", - title: t("app.login"), - component: UserWindow, - translatable: false, - }, { name: "sources", id: "3", @@ -163,15 +148,6 @@ const associAppWindow = [ component: FavStaredWindow, translatable: true, }, - { - name: "chatbot", - id: "8", - title: t("app.chatbot"), - component: ChatbotWindow, - width: "400px", - height: "600px", - translatable: false, - }, { name: "aboutNewsOrg", id: "9", @@ -194,20 +170,6 @@ const associAppWindow = [ component: NewsViewWindow, translatable: true, }, - { - name: "privacypolicy", - id: "12", - title: t("app.privacypolicy"), - component: PrivacyPolicyWindow, - translatable: false, - }, - { - name: "tos", - id: "13", - title: t("app.tos"), - component: TOSWindow, - translatable: false, - }, { name: "onboard", id: "14", @@ -751,7 +713,10 @@ setInterval(async () => { > {{ t("popup.stay") }} - @@ -822,7 +787,8 @@ setInterval(async () => { -
+ + diff --git a/server/api/ai/chat/[slug].ts b/server/api/ai/chat/[slug].ts deleted file mode 100644 index 619cbcb..0000000 --- a/server/api/ai/chat/[slug].ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Groq } from "groq-sdk"; -import sql from "~/server/components/postgres"; - -const groq = new Groq(); - -export default defineEventHandler(async (event) => { - const host = getRequestHost(event); - const protocol = getRequestProtocol(event); - const hears = getRequestHeaders(event); - const slug = getRouterParam(event, "slug"); - const body = await readBody(event); - if (!slug) { - throw createError({ - statusCode: 400, - message: "A UUID is required for this action.", - }); - } - - const getChatHistory = await sql` - select * from chat_history - where uuid = ${slug} - order by created_at asc - `; - - const buildURL = protocol + "://" + host + "/api/news/get/lt/" + "LX30VwG"; - const data = await fetch(buildURL); - const fetchNewsArticle = await data.json(); - - // Set headers for Server-Sent Events - setHeader(event, "Content-Type", "text/plain; charset=utf-8"); - setHeader(event, "Cache-Control", "no-cache"); - setHeader(event, "Connection", "keep-alive"); - setHeader(event, "Access-Control-Allow-Origin", "*"); - - const chatCompletion = await groq.chat.completions.create({ - messages: [ - { - role: "system", - content: `You are a news chat, the following content will be used to chat with the user title: ${fetchNewsArticle.title} article: ${fetchNewsArticle.paragraph} origin: ${fetchNewsArticle.origin} author: ${fetchNewsArticle.author}`, - }, - ...getChatHistory.map((chat) => ({ - role: chat.role, - content: chat.content, - })), - { - role: "user", - content: body.message, - }, - ], - model: "gemma2-9b-it", - temperature: 0.71, - max_completion_tokens: 1024, - top_p: 1, - stream: true, - stop: null, - }); - - /* - await sql` - INSERT INTO chat_history (uuid, role, content) - VALUES (${slug}, 'user', ${body.message}) - `; */ - - let assistantResponse = ""; - - // Create a readable stream - const stream = new ReadableStream({ - async start(controller) { - try { - for await (const chunk of chatCompletion) { - const content = chunk.choices[0]?.delta?.content || ""; - if (content) { - assistantResponse += content; - // Send chunk to client - controller.enqueue(new TextEncoder().encode(content)); - } - } - - /* - if (assistantResponse) { - await sql` - INSERT INTO chat_history (uuid, role, content) - VALUES (${slug}, 'assistant', ${assistantResponse}) - `; - } */ - - controller.close(); - } catch (error) { - controller.error(error); - } - }, - }); - - return sendStream(event, stream); -}); diff --git a/server/api/ai/chat/actions/findUserChatId.ts b/server/api/ai/chat/actions/findUserChatId.ts deleted file mode 100644 index 5f514cb..0000000 --- a/server/api/ai/chat/actions/findUserChatId.ts +++ /dev/null @@ -1,5 +0,0 @@ -export default defineEventHandler(async (event) => { - return { - hello: "hello", - }; -}); diff --git a/server/api/ai/summarize/[slug].ts b/server/api/ai/summarize/[slug].ts index a708f14..d7fe8d5 100644 --- a/server/api/ai/summarize/[slug].ts +++ b/server/api/ai/summarize/[slug].ts @@ -1,6 +1,7 @@ import { Groq } from "groq-sdk"; import sql from "~/server/components/postgres"; import { checkIfUserHasCustomGroqKey } from "~/server/components/customgroqsystem"; +import getEnvFromDB from "~/server/components/getEnvFromDB"; export default defineEventHandler(async (event) => { const host = getRequestHost(event); @@ -16,8 +17,9 @@ export default defineEventHandler(async (event) => { apiKey: doesTheUserHasACustomGroqApiAndWhatIsIt.customApi, }); } else { + const groq_api_key = await getEnvFromDB("groq_api_key"); groqClient = new Groq({ - apiKey: process.env.GROQ_API_KEY, + apiKey: groq_api_key, }); } const query = getQuery(event); diff --git a/server/api/create_database.ts b/server/api/create_database.ts index bf6fbfb..de5bbad 100644 --- a/server/api/create_database.ts +++ b/server/api/create_database.ts @@ -60,6 +60,12 @@ export default defineEventHandler(async (event) => { ) `; + const createGlobalVars = await sql` + CREATE TABLE IF NOT EXISTS global_vars ( + NAME TEXT PRIMARY KEY NOT NULL, + VAR TEXT NOT NULL + ) + `; return { createUsers: createUsers, usersList: usersList, @@ -67,5 +73,6 @@ export default defineEventHandler(async (event) => { createSources: createSources, createUserOtherData: createUserOtherData, createArticlesArchive: createArticlesArchive, + createGlobalVars: createGlobalVars, }; }); diff --git a/server/api/download/news-article-archive.json.ts b/server/api/download/archive.ts similarity index 100% rename from server/api/download/news-article-archive.json.ts rename to server/api/download/archive.ts diff --git a/server/api/user/login.ts b/server/api/user/login.ts index 67dfd42..fbe3721 100644 --- a/server/api/user/login.ts +++ b/server/api/user/login.ts @@ -1,16 +1,11 @@ import sql from "~/server/components/postgres"; import { v4 as uuidv4 } from "uuid"; import argon2 from "argon2"; +import getEnvFromDB from "~/server/components/getEnvFromDB"; const defaultAvatarUrl = "https://s3.yhw.tw/news-analyze/avatar/default.png"; export default defineEventHandler(async (event) => { - const salt = process.env.PASSWORD_HASH_SALT; - if (!salt) { - return { - error: "SALT_NOT_FOUND", - }; - } const body = await readBody(event); const { username, password } = body; console.log(password); @@ -33,6 +28,7 @@ export default defineEventHandler(async (event) => { where username = ${username}`; console.log(fetchUserInfo[0]); if (fetchUserInfo.length === 0) { + const salt = await getEnvFromDB("password_hash_salt"); const hashedPassword = await argon2.hash(salt + password); const userUUID = uuidv4(); const createNewUser = await sql` diff --git a/server/components/getEnvFromDB.ts b/server/components/getEnvFromDB.ts new file mode 100644 index 0000000..0a8eae3 --- /dev/null +++ b/server/components/getEnvFromDB.ts @@ -0,0 +1,16 @@ +import sql from "~/server/components/postgres"; +interface variReturn { + name: string; + var: string; +} +export default async function (vari: string) { + const fetchVar = await sql` + SELECT * FROM global_vars + WHERE NAME = ${vari}`; + if (fetchVar.length === 0) { + throw new Error( + "Cannot find var in the database. Have you followed this? https://github.com/hpware/news-analyze?tab=readme-ov-file#notes", + ); + } + return fetchVar[0].var; +} diff --git a/server_fixes.md b/server_fixes.md deleted file mode 100644 index e6965ce..0000000 --- a/server_fixes.md +++ /dev/null @@ -1,64 +0,0 @@ -# Server Fixed -(This file is NOT related to neighbourhood, but it is some stuff I learned during the down time of the server) - -## Timeline -Aprox. 10 PM UTC+8 - I found out that the server is running an outdated version of the app and tried using `docker compose pull`, but saw 192.168.1.1:53 is not a Server, and tried to fix it, and broke off the connection to the internet. - -11:40-ish PM UTC+8 Server is back online. - -## So what is the issue? -Well, My issue is one of my config files included a "on", which is why the PPPoE conenction does not work anymore. - -Image: -![](/.github/OTHER/ig_story_58m.png) - -And also I wrote a super stupid cron fix, which is below. - -## My stupid cron fix: -Cron Job: -``` -0 * * * * "bun run /hardpushrevolvconf.ts" > /dev/null -``` - -Here is the script I used to force the change of my resolv.conf file: -```typescript -import { file, $ } from "bun"; - -function sendDataToSlack(text: string) { - fetch("{slack_web_hook_to_one_of_my_channels_in_hackclub}", { - method: "POST", - headers: { - "Content-Type": "application-json" - }, - body: JSON.stringify({ text: text }) - }) - return; -} - -const resolvConfPath = "/etc/resolv.conf"; -const resolvConf = file(resolvConfPath); -const resolvConfText = await resolvConf.text(); - -if (resolvConfText.includes("192.168.1.1")) { - // Auto git config - await $`git add .` - await $`git commit -a -m "Auto Commit by the server ${Date().now}, before doing stuff into resolvConf"` - try { - await resolvConf.write("nameserver 8.8.8.8\n"); - sendDataToSlack(`${resolvConfPath} updated successfully.`); - } catch (error) { - sendDataToSlack(`Failed to write to ${resolvConfPath}:`, error); - sendDataToSlack( - "This likely happened because you didn't run the script with root privileges (e.g., 'sudo bun run script.ts')." - ); - } - await $`git add .` - await $`git commit -a -m "Auto Commit by the server ${Date().now}, after doing stuff into resolvConf"` - await $`git push` -} else { - sendDataToSlack( - "Did not find '192.168.1.1'. No changes have been made." - ); -} - -```