Skip to content

Commit

Permalink
Add LINK file
Browse files Browse the repository at this point in the history
  • Loading branch information
bbakyun committed Dec 1, 2024
1 parent 12e4f16 commit c408c29
Show file tree
Hide file tree
Showing 69 changed files with 20,222 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.env
link.pem
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
# 6th-DeploySession-LINK
Khuda_6th_deploy_session

Conference Project - khuda_4th_data_business_link_project

## L I N K

Link
Is
Not
Kind

'링크는 친절하지 않다. 우리가 친절하게 보여주겠다!' 라는 취지에서 시작한 프로젝트입니다.

크롬 익스텐션을 통해 링크를 저장하고 링크 개인 저장소를 위한 프로젝트입니다.

링크를 하위 키워드/상위 카테고리 별로 필터링하여 볼 수 있습니다.

공부하는 모든 쿠다인을 위해 배포를 계획하고 있습니다.
10 changes: 10 additions & 0 deletions chrome_extension/background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
chrome.runtime.onInstalled.addListener(() => {
console.log("Extension Installed");
});

chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ["content.js"],
});
});
9 changes: 9 additions & 0 deletions chrome_extension/content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "getURL") {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const activeTab = tabs[0];
sendResponse({ url: activeTab.url });
});
return true; // Indicates to Chrome that we will respond asynchronously.
}
});
Binary file added chrome_extension/icons/khuda_logo_128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chrome_extension/icons/khuda_logo_16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chrome_extension/icons/khuda_logo_48.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions chrome_extension/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"manifest_version": 3,
"name": "Link",
"description": "Save links with summaries and keywords",
"version": "1.0",
"action": {
"default_popup": "popup/popup.html",
"default_icon": {
"16": "icons/khuda_logo_16.png",
"48": "icons/khuda_logo_48.png",
"128": "icons/khuda_logo_128.png"
}
},
"background": {
"service_worker": "background.js"
},
"permissions": ["activeTab", "storage"],
"host_permissions": ["<all_urls>"],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
]
}
78 changes: 78 additions & 0 deletions chrome_extension/popup/popup.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
body {
width: 300px;
height: 400px;
font-family: Arial, sans-serif;
background-color: #000;
color: #fff;
margin: 0;
padding: 10px;
box-sizing: border-box;
}

#content {
display: flex;
flex-direction: column;
align-items: center;
}

#link-info {
text-align: center;
margin-bottom: 20px;
}

#thumbnail {
width: 100%;
height: auto;
max-height: 100px; /* 이미지 크기 제한 */
object-fit: cover; /* 이미지를 잘라서 크기에 맞추기 */
margin-bottom: 10px;
}

#title {
font-size: 16px;
color: #ffeb3b;
margin: 5px 0;
}

#description {
font-size: 14px;
color: #fff;
margin: 5px 0;
}

#keywords {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 5px;
margin-bottom: 15px;
}

.keyword-button {
background-color: #ffeb3b;
border: none;
padding: 5px 10px;
cursor: pointer;
border-radius: 10px;
font-size: 12px;
}

#buttons {
display: flex;
justify-content: space-between;
width: 100%;
}

button {
width: 45%;
padding: 10px;
background-color: #ffeb3b;
border: none;
cursor: pointer;
font-size: 14px;
border-radius: 5px;
}

button:hover {
background-color: #ffe500;
}
23 changes: 23 additions & 0 deletions chrome_extension/popup/popup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Link</title>
<link rel="stylesheet" href="popup.css" />
</head>
<body>
<div id="content">
<div id="link-info">
<img id="thumbnail" src="" alt="Thumbnail" />
<h2 id="title">Loading...</h2>
<p id="description">Loading...</p>
<div id="keywords"></div>
</div>
<div id="buttons">
<button id="add-button">Add to My Links</button>
<button id="mylinks-button">My Links</button>
</div>
</div>
<script src="popup.js"></script>
</body>
</html>
105 changes: 105 additions & 0 deletions chrome_extension/popup/popup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
function generateUUID() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0,
v = c == "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}

// 로컬 스토리지에서 UUID를 가져오거나 생성
function getUUID() {
let uuid = localStorage.getItem("user_uuid");
if (!uuid) {
uuid = generateUUID();
localStorage.setItem("user_uuid", uuid);
}
return uuid;
}

document.addEventListener("DOMContentLoaded", () => {
const addButton = document.getElementById("add-button");
const mylinksButton = document.getElementById("mylinks-button");
const userUUID = getUUID();

// 현재 탭의 URL을 가져와 Django 서버에 요청
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const url = tabs[0].url;

fetch("http://218.209.109.43:8000/api/extract_from_url/", {
// Django 서버의 공인 IP 주소 사용
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ url, user_uuid: userUUID }), // user_uuid 추가
})
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then((data) => {
document.getElementById("title").innerText = data.title || "No Title";
document.getElementById("description").innerText =
data.summary || "No Summary";
document.getElementById("thumbnail").src =
data.image_url || "default-thumbnail.png";

const keywordsDiv = document.getElementById("keywords");
keywordsDiv.innerHTML = ""; // 기존 내용을 지움
data.keywords.forEach((keyword) => {
const keywordButton = document.createElement("button");
keywordButton.className = "keyword-button";
keywordButton.innerText = keyword;
keywordsDiv.appendChild(keywordButton);
});

// "Add to My Links" 버튼 클릭 시 데이터 저장
addButton.addEventListener("click", () => {
const title = document.getElementById("title").innerText;
const description = document.getElementById("description").innerText;
const image_url = document.getElementById("thumbnail").src;
const keywords = Array.from(
document.getElementsByClassName("keyword-button")
).map((button) => button.innerText);

fetch("http://218.209.109.43:8000/api/links/", {
// Django 서버의 공인 IP 주소 사용
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
url,
title,
description,
keywords,
image_url,
user_uuid: userUUID, // user_uuid 포함
}),
})
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then((data) => {
alert("당신의 마음속에 저장 완료♥");
})
.catch((error) => {
console.error("Error adding link:", error);
});
});
})
.catch((error) => {
console.error("Error fetching data from server:", error);
});
});

// "My Links" 버튼 클릭 시 React 앱으로 이동
mylinksButton.addEventListener("click", () => {
window.open(`http://218.209.109.43:3000?user_uuid=${userUUID}`); // React 앱의 URL 사용
});
});
Binary file added django/link_app/db.sqlite3
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
16 changes: 16 additions & 0 deletions django/link_app/link_app/asgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
ASGI config for link_app project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'link_app.settings')

application = get_asgi_application()
Loading

0 comments on commit c408c29

Please sign in to comment.