Ứng dụng CLI quản lý bài viết

Ứng dụng CLI quản lý bài viết

Những mẩu tin ngắn hàng ngày dành cho bạn
  • countless.dev là một trang web khá thú vị khi mà nó so sánh giá tiền sử dụng các mô hình LLMs của các nhà cung cấp khác nhau.

    Tại đây bạn có thể nhìn thấy tất cả các mô hình ngôn ngữ lớn phổ biến bởi các nhà cung cấp như OpenAI, Azure, Mistral... Bảng giá cho mỗi 1M tokens đầu vào/ra. Hoặc thậm chí có thể so sánh chúng với nhau để tìm ra nhà cung cấp hoặc mô hình rẻ nhất tuỳ theo mục đích sử dụng.

    » Xem thêm
  • 1,2 năm trước, Kubernetes (k8s) tự nhiên được nhắc đến như một hiện tượng, chắc vì nó bá quá nên ai cũng muốn học và sử dụng. Nó là một công cụ "Automating deployment, scaling, and management of containerized applications" - Vâng! nghe hay ho đấy chứ 🤤.

    Hồi đó thì mình đang đam mê với Docker, đặc biệt là Docker Swarm, cũng tương tự như k8s ý nhưng ở quy mô nhỏ hơn. Docker Swarm thì có vẻ ít phức tạp hơn nhiều so với k8s. Mà như thế cũng tốt vì nó đã và đang đáp ứng rất tốt nhu cầu sử dụng của mình lúc đó, lại còn bớt đi phần phức tạp, lằng nhằng.

    Ấy thế mà 1-2 tháng trở lại đây, các bài viết có tiêu đề "bạn có thực sự cần đến Kubernetes" lại đang nổi lên với tần suất dày hơn. Quả thật k8s rất mạnh nhưng cũng quá phức tạp. Tại sao phải cố dùng dao "mổ trâu để giết gà" cơ chứ? Trừ khi bạn lường trước được độ phức tạp khi muốn áp dụng một công nghệ. Một cái nữa k8s tiêu tốn tài nguyên và nguồn lực ghê ghớm, để vận hành được nó không đơn giản là dựng lên được là xong mà còn phải có rất nhiều nhiều kiến thức nữa 😨.

    À, chắc cũng một phần nữa là do các "ông lớn" đang tập trung đẩy mạnh vào Serverless, giảm bớt sự phức tạp trong khâu vận hành đi, thay vào đó là nên tập trung vào phát triển ứng dụng.

    Bên cạnh đó, thì cái tên WASM cũng đang được nhắc đến rất là nhiều 🤔

    Do you really need Kubernetes in your company/startup? | dev.to

    Do You Really Need Kubernetes?

    » Xem thêm
  • Trước mình cứ khen lấy khen để Serverless, rằng tối ưu chi phí xuống 0đ để duy trì blog các thứ. Đúng là như vậy thật! Nhưng bên cạnh đó serverless cũng có các mặt tối đáng để lưu tâm đấy!

    Hôm kia mình phải mất ngày trời để truy tìm và khắc phục sự cố chỉ vì gọi hàm build-in của Cloudflare KV. Cụ thể là hàm list với limit 1000 - tức là một lần gọi nó trả về 1000 keys của KV. Cơ mà đời không như là mơ. Con số 1000 chỉ là trên lý thuyết. Lúc thì trả về vài trăm, lúc thì vài chục, thậm chí lúc thì lẹt đẹt có vài cái. Thế là làm tắc nghẽn cả hệ thống. À mà cũng không phải là nghẽn mà là hệ thống "nhàn rỗi" quá không có việc gì để làm, trong khi thực tế đáng ra nó phải xử lý cả trăm ngàn cái keys cơ 🥲

    » Xem thêm

Vấn đề

Xin chào các độc giả của 2coffee.dev. Một tuần nữa lại trôi qua, nhanh đến nỗi mà khi nhìn lại trang chủ, không ngờ rằng mình lại ngừng viết trong một khoảng thời gian dài như thế. Thành thật mà nói tuần vừa rồi khá là bận rộn, tôi vừa tập trung phát hành một bản cập nhật quan trọng cho sản phẩm tại nơi đang làm việc. Có lẽ vì thế mà khái niệm thời gian đã tạm thời bị vùi lấp. Hmm... Phải nghĩ ra xem có gì để kể không chứ!

Song song với việc đó, tôi đang cố gắng tối ưu hoá lại trải nghiệm người dùng cho trang blog. Bằng cách sửa một số lỗi tồn đọng từ trước, làm cho đường dẫn đến liên kết hiển thị rõ ràng hơn, thêm một vài hiệu ứng vui mắt và bổ sung thêm một số tinh chỉnh giao diện. Chỉ nhiêu đấy thôi mà cũng ngốn thời gian ra mặt. Sáng đi làm, tối về quay cuồng với guồng tối ưu không hồi kết.

Một vấn đề mới phát sinh trong lúc tối ưu hoá là quá trình render markdown lại gặp vấn đề. Cụ thể là khi sử dụng một số thẻ mới thì trang web bị vỡ giao diện. Chà! Kiếp nạn này bao giờ mới hết. Nếu nhớ không nhầm, phải có 2-3 bài viết nói về những vấn đề đã gặp phải với markdown. Cũng có khả năng là lúc trước đã quá xem nhẹ nên bây giờ phải đối mặt với những vấn đề như thế này.

Đằng nào cũng phải đụng đến nên quyết tâm sửa lại luôn một thể. Không sử dụng showdown nữa mà chuyển sang một thư viện khác có tên là marked.js. Chọn luôn tiêu chuẩn gfm của Github để định dạng. Làm như vậy sẽ hạn chế được những thay đổi sau này.

Trong rất nhiều bài viết trước đây, tôi có sử dụng một thẻ markdown để hiển thị hình ảnh thumbnail cho bài viết. Nhưng từ sau khi đập đi xây lại, phần hiển thị hình ảnh thumbnail đã được viết trực tiếp vào trong code. Còn phần hình ảnh đầu bài viết dùng code để tạm ẩn đi. Bây giờ chuyển sang tính năng mới, cần phải loại bỏ hết thẻ markdown bị thừa.

Nên công việc tiếp theo là cần sửa lại hàng loạt bài viết. Trang web có cách vận hành khá thú vị, đó là trang quản lý hết sức sơ sài. Không như những phiên bản trước có một trang quản lý "xịn sò", phiên bản này chỉ có một vài tính năng vừa đủ như tạo/cập nhật bài viết. Để truy cập vào trang chỉnh sửa, chỉ cần thêm một postfix /edit vào sau đường dẫn đến bài viết thì nó sẽ dẫn đến trang chỉnh sửa. Tất nhiên là trước đó phải đăng nhập bằng tài khoản có quyền admin, còn không thì bạn sẽ thấy một thông báo lỗi rằng trang không khả dụng.

Như vậy đếm sơ sơ có hơn 300 bài viết cần phải sửa lại, tương đương phải thực hiện lại các thao tác chỉnh sửa hơn 300 lần 🤮. Chưa kể mạng không phải lúc nào cũng tải được trang web trong vòng 3s. Vì thế lại một lần nữa, tôi tìm đến giải pháp CLI.

Ứng dụng CLI

Ý tưởng về một ứng dụng CLI giúp quản lý bài viết không mới. Thực tế từ lúc xây dựng phiên bản mới cho trang blog tôi đã nghĩ đến việc quản lý bài viết bằng những dòng lệnh. Mỗi bài viết là một file markdown, lưu trữ ở dưới máy, chỉnh sửa xong thì dùng một lệnh để xuất bản các bài viết lên là được. Vừa nhanh mà vừa tiện. Nhưng đến khi nghiêm túc ngồi "break" ra những thứ cần làm thì chao ôi... có lẽ mình nên làm cách đơn giản hơn. Hãy nhớ lại sứ mệnh của 2coffee.dev, mang đến những bài viết chất lượng chứ không phải là cặm cụi nửa tháng mà vẫn chưa ra ngô ra khoai.

Giờ đây thời cơ đã đến, đã có những thứ xây dựng từ trước và tận dụng lại được. Ứng dụng CLI xuất phát từ nhu cầu: quản lý được bài viết và chỉnh sửa phải nhanh gọn. Vì thế chức năng cơ bản chỉ cần kéo (pull) được danh sách bài viết về, chỉnh sửa hàng loạt rồi đẩy (push) bài viết lên, lấy cảm hứng tương tự như cách dùng git.

Nếu bạn còn nhớ về bài viết ứng dụng cli để tối ưu hoá hình ảnh, tôi đã tạo ra một cli xử lý hình ảnh từ trước đó. Ban đầu định viết tiếp phần code mới vào đây nhưng thực tế phải viết thêm nhiều code nên cách nhanh nhất là viết vào chung với dự án page-fresh - vốn là trang blog này. Nó có chứa nhiều mã giúp lấy dữ liệu từ máy chủ, mình có thể tận dụng để không cần phải viết lại nữa.

Để đơn giản hết mức có thể, các tệp pull.ts, push.ts... để đại diện cho lệnh pullpush. pull để kéo bài viết về còn push để xuất bản bài viết. Mỗi lúc cần chạy thì cú pháp sử dụng sẽ là:

$ deno run -A pull.ts
$ deno run -A push.ts

Để hỗ trợ thêm cờ (flag), kiểu như là --change, --force giống như các ứng dụng CLI chính thống thì cứ gõ thêm vào deno run rồi dùng Deno.args để phân tích dữ liệu và xử lý.

const args = Deno.args;

const flags: { [key: string]: string | boolean } = {};
for (let i = 0; i < args.length; i++) {
  if (args[i].startsWith("--")) {
    const flag = args[i].substring(2); // loại bỏ '--'
    if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
      flags[flag] = args[i + 1]; // lấy giá trị của flag
      i++;
    } else {
      flags[flag] = true;
    }
  }
}

pull.ts chứa mã lấy dữ liệu về. Khi chạy lệnh pull nó sẽ kéo tất cả nội dung bài viết về và lưu lại dưới dạng tệp *.md, với * là url của bài viết.

$ deno run -A cli/commands/pull.ts 
ℹ Kéo về 212 bài viết, bỏ qua 0 bài viết, thay đổi 0 bài viết (VI)
ℹ Kéo về 202 bài viết, bỏ qua 0 bài viết, thay đổi 0 bài viết (EN)
✔ Đã xong

Sau đó tôi tạo thêm một tệp article.ts để kiểm tra các bài viết đã thay đổi ở dưới máy. Đó là các bài viết được chỉnh sửa và chuẩn bị để xuất bản. Ví dụ:

$ deno run -A cli/commands/article.ts --change
ℹ Các thay đổi của bài viết tiếng Việt:
- 1-thang-hoc-rust-nhung-dieu-co-ban-cua-ngon-ngu-lap-trinh-rust.md
ℹ Các thay đổi của bài viết tiếng Anh:
- a-compilation-of-free-and-high-quality-serverless-databases.md
✔ Đã xong

Sau khi sửa xong, dùng lệnh push để xuất bản một bài chỉ định trước. Ví dụ:

$ deno run -A cli/commands/push.ts --file data/1-thang-hoc-rust-nhung-dieu-co-ban-cua-ngon-ngu-lap-trinh-rust.md

Hoặc push toàn bộ những bài đã sửa. Ví dụ:

$ deno run -A cli/commands/push.ts --change
ℹ Tìm thấy 1 bài viết tiếng Việt, 1 bài viết tiếng Anh
- 1-thang-hoc-rust-nhung-dieu-co-ban-cua-ngon-ngu-lap-trinh-rust.md
- a-compilation-of-free-and-high-quality-serverless-databases.md
✔ Đã cập nhật 1-thang-hoc-rust-nhung-dieu-co-ban-cua-ngon-ngu-lap-trinh-rust.md
✔ Đã cập nhật a-compilation-of-free-and-high-quality-serverless-databases.md
✔ Đã xong

Ngay lập tức các bài viết tìm thấy được đẩy lên. Trong push.ts có một hàm gọi API để xuất bản bài viết với quyền admin. Nên buộc phải có cookie của tài khoản quản trị. Cookie có thể lấy bằng cách vào trang web sao chép rồi dán thẳng vào trong code. Nhưng cookie có thời hạn khá ngắn cho nên viết thêm một tệp login.ts xử lý việc lấy cookie sẽ tiện hơn cho quá trình sử dụng sau này.

Cơ chế login cũng đơn giản. Bên trong login.ts khởi tạo một server cục bộ lắng nghe ở cổng 3069, bên trong có 1 endpoint tên là /callback. Khi gọi vào 2coffee.dev, ví dụ như là https://2coffee.dev/auth?redirect_url=http://localhost:3069/callback?token=<cookie> thì nó sẽ gọi lại vào endpoint /callback kèm theo token chính là cookie của admin, với điều kiện là admin đã đăng nhập từ trước. Lưu lại token vào certificate.txt để sử dụng cho các lần tiếp theo.

Kết hợp tất cả lại, tôi đã có 4 tệp login.ts, pull.ts, push.ts, articles.ts. Nếu cứ gõ đi gõ lại deno run sẽ rất dài, vì thế hãy nghĩ cách tối giản lại. Một lệnh gì đó giống như như là 2cf, khi đó chỉ cần gõ 2cf login, 2cf pull, 2cf push... tiện hơn biết bao.

Tạo một tệp cli.sh ngay trong thư mục của dự án page-fresh:

#!/bin/bash

case $1 in
  login)
    cd /Users/hoaitx/src/hoaitx/page-fresh && deno run -A cli/commands/login.ts $2
    ;;
  pull)
    cd /Users/hoaitx/src/hoaitx/page-fresh && deno run -A cli/commands/pull.ts $2
    ;;
  push)
    cd /Users/hoaitx/src/hoaitx/page-fresh && deno run -A cli/commands/push.ts $2
    ;;
  article)
    cd /Users/hoaitx/src/hoaitx/page-fresh && deno run -A cli/commands/article.ts $2
    ;;
  *)
    echo "Usage: $0 {login|pull|push|article}"
    ;;
esac

Như vậy lúc này chỉ cần ./cli.sh login, ./cli.sh pull...

Ở đây tôi dùng Mac và cài Oh My Zsh nên có thể đặt alias cho dòng lệnh. Tiếp tục mở tệp .zshrc và thêm vào function 2cf().

function 2cf() {
    /Users/hoaitx/src/hoaitx/page-fresh/cli.sh "$@"
}

Reload lại .zshrc:

$ source ~/.zshrc

Thế là đã xong, từ giờ đã có thể dùng lệnh 2cf:

$ 2cf login
$ 2cf pull
$ 2cf push
...

Cuối cùng để cho CLI trở nên sinh động hơn, tôi sử dụng thêm 2 package là orachalk. ora dùng để tạo hiệu ứng xử lý còn chalk để thay đổi màu sắc của văn bản trong terminal.

Trong tương lai, tôi sẽ tiếp tục phát triển ứng dụng CLI này với mục đích thay thế hoàn toàn trang quản trị và tiến tới một vài tính năng tự động khác.

Cao cấp
Hello

Tôi & khao khát "chơi chữ"

Bạn đã thử viết? Và rồi thất bại hoặc chưa ưng ý? Tại 2coffee.dev chúng tôi đã có quãng thời gian chật vật với công việc viết. Đừng nản chí, vì giờ đây chúng tôi đã có cách giúp bạn. Hãy bấm vào để trở thành hội viên ngay!

Bạn đã thử viết? Và rồi thất bại hoặc chưa ưng ý? Tại 2coffee.dev chúng tôi đã có quãng thời gian chật vật với công việc viết. Đừng nản chí, vì giờ đây chúng tôi đã có cách giúp bạn. Hãy bấm vào để trở thành hội viên ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.
Author

Xin chào, tôi tên là Hoài - một anh Dev kể chuyện bằng cách viết ✍️ và làm sản phẩm 🚀. Với nhiều năm kinh nghiệm lập trình, tôi đã đóng góp một phần công sức cho nhiều sản phẩm mang lại giá trị cho người dùng tại nơi đang làm việc, cũng như cho chính bản thân. Sở thích của tôi là đọc, viết, nghiên cứu... Tôi tạo ra trang Blog này với sứ mệnh mang đến những bài viết chất lượng cho độc giả của 2coffee.dev.Hãy theo dõi tôi qua các kênh LinkedIn, Facebook, Instagram, Telegram.

Bạn thấy bài viết này có ích?
Không

Bình luận (4)

Nội dung bình luận...
Avatar
Xuân Hoài Tống3 tuần trước
Thôi nào các bác, đăng nhập vào có khi vui hơn ấy 😅
Trả lời
Avatar
Ẩn danh3 tuần trước
Gòi toàn ẩn danh thật thật giả giả 👈🫵👉
Trả lời
Avatar
Ẩn danh3 tuần trước
bài viết hữu ích
Trả lời
Avatar
Ẩn danh3 tuần trước
tuyệt's vời
Trả lời