Plausible.io용 xbar 플러그인 작성

현재 방문자 수를 보기 위해 xbar-app용 JS-플러그인을 작성하는 방법

자바스크립트에서 xbar-plugin 작성하기

주말 프로젝트로 xbar용 간단한 플러그인을 작성하고 싶었습니다. 최근에 우연히 발견한 응용 프로그램입니다. xbar 자체는 프로그래밍 언어 "Go"로 작성되었으며 개발자가 macOS의 메뉴 모음에 대한 사용자 지정 메뉴 항목을 작성할 수 있도록 기본 서비스로 "Wails"를 사용합니다(예, 현재 macOS에만 제한됨).

xbar의 좋은 점은 Javascript도 포함하여 다양한 프로그래밍 언어를 지원한다는 것입니다. 따라서 웹 개발자로서 개인 정보 보호 분석 서비스인 Plausible.io에 연결하는 사용자 지정 플러그인을 작성하는 것이 얼마나 쉬운지 알고 싶었습니다. 목표는 현재 이 웹 앱에 있는 모든 현재 사용자를 렌더링하는 것입니다. 글을 쓰는 시점에서 풀 리퀘스트는 아직 검토 중입니다.

Image 52d29c4414ce

Image 67e4f6e5107d

기본 xbar 설정

xbar는 Mac에 다운로드하여 설치할 수 있습니다. 처음 시작하면 다운로드 가능하고 게시된 모든 플러그인이 포함된 화면을 사용하여 원하는 플러그인을 얻을 수 있습니다.

설치 프로세스는 단순히 플러그인의 소스 코드(플러그인당 단일 파일)를 xbar가 현재 설치된 모든 플러그인을 읽는 특수 폴더에 복사합니다. 플러그인 작성을 시작하려면 디렉토리에 파일을 만들고 해킹을 시작하면 됩니다. 정돈 된!

xbar 파일 이름 규칙

파일 이름은 점으로 구분된 세 부분으로 구성됩니다.

  • 고유한 플러그인 이름
  • CRON 작업과 유사한 코드가 실행되는 시간 간격
  • 공통 파일 접미사
plausible.1m.js

JS에서 xbar 플러그인 코딩하기

이제 코딩을 시작할 준비가 되었습니다! 먼저 노드 인스턴스를 찾아야 하는 위치를 xbar에 알려주는 필수 shebang 지시문을 포함합니다.

#!/usr/bin/env /usr/local/bin/node

다음 부분은 일부 메타 데이터를 추가하는 것입니다. 물론 로컬 개발의 경우 생략할 수 있지만 다음은 Plausible-plugin에 사용하는 것입니다.

// Metadata allows your plugin to show up in the app, and website.
//
//  <xbar.title>Plausible Tracker</xbar.title>
//  <xbar.version>v1.0</xbar.version>
//  <xbar.author>Tom Schönmann</xbar.author>
//  <xbar.author.github>flaming-codes</xbar.author.github>
//  <xbar.desc>See who's on your site at-a-glance.</xbar.desc>
//  <xbar.dependencies>node</xbar.dependencies>
//  <xbar.abouturl>https://flaming.codes</xbar.abouturl>
//  <xbar.image>https://raw.githubusercontent.com/flaming-codes/xbar-plausible-stats/main/plausible-icon-36-36-144.png</xbar.image>

플러그인을 실행하는 데 필요한 모든 것입니다. 이제 사용자의 Node.js 인스턴스에 의해 실행되는 순수 Javascript로 코딩할 수 있는 캔버스가 있습니다. 이는 "https"와 같은 모든 핵심 노드 패키지에 액세스할 수 있음을 의미합니다. 내 사용 사례의 경우 사용자를 추적하려면 Plausible.io-API에서 가져오기만 하면 되므로 이것이 내가 필요한 모든 것입니다.

다음 코드는 내가 이야기할 가치가 있다고 생각하는 가장 관련성이 높은 부분을 보여줍니다. 전체 코드는 관련 공개 저장소, 이 페이지 끝에 있는 부록의 링크에서 사용할 수 있습니다.

// Here you see how to make network
// requests with 'https'-only.
// This is a native node-lib that
// works w/ data streams, as you'll see.

const https = require("https");

// Those have to edited by the
// user directly in the file,
// after it has been downloaded
// (aka installed)!
const SITE_ID = "";
const API_KEY = "";

// ... other code ...

async function fetcher() {
  return new Promise((resolve, reject) => {
    let body = "";
    const request = {
      host: "plausible.io",
      path: `/api/v1/stats/realtime/visitors?site_id=${SITE_ID}`,
      method: "GET",
      headers: {
        Authorization: `Bearer ${API_KEY}`,
      },
    };

    try {
      const req = https.get(request, (res) => {
        res.on("data", (data) => {
          body += data;
        });
        res.on("end", () => {
          resolve(JSON.parse(body));
        });
      });

      req.on("error", (error) => {
        console.error(error);
      });

      req.end();
    } catch (error) {
      reject(error);
    }
  });
}
// I've implemented an array of tuples
// that hold an icon + count threshold
// when to active it.

// The first entry doesn't render a 
// string (which can be direclty used),
// but rather a mapping that results in
// the following code:
//
// `image="..." font=Menlo color=white`
//
// This is a special syntax that tells
// xbar to render a base64 image w/
// a custom font and color.
//
// 'plausibleIconWhite' is just the string
// for the base64-image.
const stepIcons = [
  [0, `${plausibleIconWhite} Menlo white`, "image font color"],
  [5, "💫"],
  [10, "⭐️"],
  [50, "🌟"],
  [100, "⚡️"],
  [500, "💥"],
];
// Actually rendering stuff in xbar
// is super simple - just output it
// with console.log(...).
//
// As you'll see, '---' define 
// separator. The first log-call
// gets rendered as acutal menu item.

const linksMenu = [
  "---",
  `🔮 Open dashboard | href=https://plausible.io/${SITE_ID}`,
  `🔥 Made by flaming.codes | href=https://flaming.codes`,
];

function renderError(props) {
  const { error } = props;
  const output = [
    "❔",
    "---",
    "No data accessible",
    "Please check your user data",
    ...linksMenu,
  ];

  console.log(output.join("\n"));
}

// Finally, I defined a single function
// where everything starts. This function
// just gets called to kick everyting off.
// Plain JS, it's that simple.

async function render() {
  const { data, error } = await fetcher()
    .then((data) => ({ data }))
    .catch((error) => ({ error }));

  if (data >= 0) return renderData({ data });
  if (error) return renderError({ error });
}

render();

xbar용 코딩은 쉽습니다.

전체 프로세스를 완료하는 데 몇 시간이 걸렸습니다. 대부분 xbar에서 API를 확인하고 스타일링을 위해 다양한 구성을 가지고 놀았습니다. 대체로, 이와 같은 간단한 플러그인을 작성하는 것은 실제로 하는 재미가 있는 많은 노력이 아닙니다. 여가 시간이 있다면, 당신도 그것을 시도해야합니다!

xbar를 가장 잘 대변하는 것은 이 유연하고 빠른 개발이 허용하는 스크립팅 기회라고 생각합니다. 클라우드 설정 또는 분석 서비스에 대한 맞춤형 추적기를 작성하여 macOS의 메뉴 막대에서 모든 지표를 한 눈에 볼 수 있도록 할 수 있습니다. 좋아요!