[nextjs]SNS Server-9(myapp19)

👉🏻 inbox_posts 테이블에 actor와 original_id필드를 추가 합니다.
Add the actor and original_id fields to the inbox_posts table.

👉🏻 original_id필드는 나중에 id(API의 id 부분)를 짧게 변환하기 위해서 만든 필드입니다.
The original_id field was created to store a shortened version of the id (the ID portion of the API) for later use.

👉🏻 Actor는 글 보낸 사람의 전체 URL입니다.
“Actor” is the full URL of the person who sent the post.

👉🏻 기존의 타임라인 UI부분의 주소에 @userid를 사용합니다.
Use @userid in the URL for the existing timeline UI section.

📁 전체 프로젝트 구조 / Overall Project Structure

myapp19/  
├── app/  (Next.js App Router)
│   ├── .well-known/webfinger/route.ts  -> webfinger
│   ├── api/posts/route.ts     -> Writing API
│   ├── api/follow/route.ts    -> Follow API(temporary)
│   ├── api/timeline/route.ts  -> Timeline API
│   ├── users/[username]/
│   │   ├── statuses/[id]/route.ts -> Indivisual Post
│   │   ├── route.ts               -> Acotr Information
│   │   ├── followers/route.ts     -> Followers List
│   │   ├── following/route.ts     -> Following List
│   │   ├── inbox/route.ts         -> Inbox
│   │   └── outbox/route.ts        -> outbox
│   ├── usersui/[username]/page.tsx  -> Timeline UI
│   ├── layout.tsx, page.tsx, globals.css
│   └── favicon.ico
├── lib/
│   ├── ap.ts                  -> Follow Accept
│   └── db.ts                  -> DB connection
├── data/
│   └── keys/                  -> private.pem, public.pem
├── data.sqlite                -> Database
├── Caddyfile                  -> https 
└── package.json

📁 프로젝트 시작(myapp19)
Project Start (myapp19)

npx create-next-app@latest

📁 SQLite설치 / Installing SQLite

cd ~/myapp19
npm install better-sqlite3
npm install -D @types/better-sqlite3

📁 DDNS,https설정 / DDNS,https settings

📁 데이터베이스 필드 추가
Add database field

✔️ inbox_posts테이블에 actor가 없다면 actor필드를 추가합니다.
If the actor field does not exist in the inbox_posts table, add it.

ALTER TABLE inbox_posts ADD COLUMN actor TEXT;
ALTER TABLE inbox_posts ADD COLUMN original_id TEXT;

1)inbox_posts테이블에 actor필드를 추가하고 posts테이블에는 추가하지 않습니다.
Add the actor field to the inbox_posts table, but do not add it to the posts table.

— 전체 DB 스키마 / Entire DB schema

sqlite> .schema
CREATE TABLE posts (
    id TEXT PRIMARY KEY,
    content TEXT NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  , username TEXT DEFAULT 'user1');
CREATE TABLE followers (
    id TEXT PRIMARY KEY,
    actor TEXT NOT NULL,
    inbox TEXT NOT NULL
  , username TEXT);
CREATE TABLE users (
  username TEXT PRIMARY KEY,
  display_name TEXT DEFAULT '',
  summary TEXT DEFAULT '',
  private_key TEXT,
  public_key TEXT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_followers_username ON followers(username);
CREATE INDEX idx_followers_actor ON followers(actor);
CREATE TABLE following (
  id TEXT PRIMARY KEY,
  actor TEXT NOT NULL,
  username TEXT NOT NULL,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_following_username ON following(username);
CREATE INDEX idx_following_actor ON following(actor);
CREATE TABLE inbox_posts (
  id TEXT PRIMARY KEY,
  actor TEXT,
  content TEXT,
  username TEXT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
, original_id TEXT);
CREATE INDEX idx_posts_username_created ON posts(username, created_at DESC);
CREATE INDEX idx_inbox_username_created ON inbox_posts(username, created_at DESC);
CREATE INDEX idx_inbox_actor ON inbox_posts(actor);
sqlite> 

✔️ 타임라인 라우트 코드 수정
Modify timeline route code

— myapp19/app/api/timeline/route.ts

// myapp19 ✅
  const timeline = db.prepare(`
    SELECT id, content, username, username as actor, created_at, 'mine' as source 
    FROM posts WHERE username = ?
    UNION ALL
    SELECT id, content, username, actor, created_at, 'inbox' as source 
    FROM inbox_posts WHERE username = ?
    ORDER BY created_at DESC
    LIMIT 50
`).all(username, username);

1)타임라인 API로 데이터베이스의 Actor를 조회합니다.
Query the database for the Actor using the Timeline API.

✔️ 타임라인 UI 라우트 코드 수정
Modify timeline UI route code.

— myapp19/app/usersui/[username]/page.tsx

... ...

  const timeline = db.prepare(`
    SELECT id, content, username, username as actor, created_at, 'mine' as source 
    FROM posts WHERE username = ?
    UNION ALL
    SELECT id, content, username, actor, created_at, 'inbox' as source 
    FROM inbox_posts WHERE username = ?
    ORDER BY created_at DESC LIMIT 50
  `).all(username, username) as any[];

... ...

  return (
    <div style={{ padding: 20 }}>
      <h1>{username} 타임라인 / Timeline</h1>
      <ul>
        {timeline.map((p:any) => (
          <li key={`${p.source}-${p.id}`}>
            [{p.source}] <b>{p.actor}</b>: {p.content} - {p.created_at}
          </li>
        ))}
      </ul>
    </div>
  );

1)타임라인UI에서 Actor를 보여줍니다.
Displays the Actor in the timeline UI.

✔️ 인박스 라우트 코드 수정
Modify inbox route code

— myapp19/app/users/[username]/inbox/route.ts

db.prepare(`
INSERT OR IGNORE INTO inbox_posts (id, actor, content, username, original_id, created_at) VALUES (?, ?, ?, ?, ?, ?)`).run(postId, actorId, content, username, note.id, note.published || new Date().toISOString());

1)DB에 Actor와 orginal_id를 저장하는 부분입니다.
This is the part that saves the Actor and original_id to the database.

✔️ 브라우저에서 아래의 주소로 테스트 해봅니다.
Try testing it in your browser using the address below.

— Timeline API

https://aloy-horizon.duckdns.org/api/timeline?username=user1
Timeline API

— Timeline UI

https://aloy-horizon.duckdns.org/usersui/user1
TImeline UI

📁 타임라인 주소에 @userid 사용하기
Using @userid in the timeline URL

✔️ myapp19/next.config.ts 코드 수정
Modify myapp19/next.config.ts code

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  /* allow domain*/
  allowedDevOrigins: ['aloy-horizon.duckdns.org', '*.duckdns.org'],

  /* host.domain.org/@userid */
  async rewrites() {
    return [
      {
        source: '/@:username',
        destination: '/usersui/:username',
      },
    ]
  }
};


export default nextConfig;

1)rewrites()함수는 nextjs예약함수라 자동실행됩니다.
The rewrites() function is a reserved Next.js function, so it executes automatically.

✔️ 서버를 재시작합니다.
Restarting the server.

ctrl + c
npm run dev

✔️ 브라우저에서 다음과 같이 접속해 봅니다.
Try accessing the following in your browser.

https://aloy-horizon.duckdns.org/@user1
@userid

요한복음 8장 32절 / John 8:32

“그리고 너희는 진리를 알게 될 것이며, 진리가 너희를 자유롭게 할 것이다.”

“Then you will know the truth ,and the truth will set you free”

Leave a Reply