洪 民憙 (Hong Minhee) :nonbinary:'s avatar

洪 民憙 (Hong Minhee) :nonbinary:

@hongminhee@hollo.social

1,113 following1,903 followers

An intersectionalist, feminist, and socialist living in Seoul (UTC+09:00). @tokolovesme's spouse. Who's behind @fedify, @hollo, and @botkit. Write some free software in , , , & . They/them.

서울에 사는 交叉女性主義者이자 社會主義者. 金剛兔(@tokolovesme)의 配偶者. @fedify, @hollo, @botkit 메인테이너. , , , 等으로 自由 소프트웨어 만듦.

()

Pinned

@hongminhee@hollo.social

Hello! I'm Hong Minhee (洪 民憙), an open source software engineer in my late 30s, living in Seoul, Korea. I'm bisexual and non-binary (they/them), and an enthusiastic advocate of free/open source software and the fediverse.

I work full-time on @fedify, an ActivityPub server framework in TypeScript, funded by @sovtechfund. I'm also the creator of @hollo, a single-user ActivityPub microblog; @botkit, an ActivityPub bot framework; Hackers' Pub, a fediverse platform for software developers; and LogTape, a logging library for JavaScript and TypeScript.

I have a long interest in East Asian languages (CJK) and Unicode. I post mostly in English here, though occasionally in Japanese or in mixed-script Korean (國漢文混用體), a traditional writing style that interleaves Chinese characters with the native Korean alphabet. Wanting to write in that style was actually one of the reasons I joined the fediverse. Feel free to talk to me in English, Korean, Japanese, or even Literary Chinese!

en.wikipedia.org

Korean mixed script - Wikipedia

Pinned

はじめまして!ソウル在住の30代後半のオープンソースソフトウェアエンジニア、洪 民憙ホン・ミンヒと申します。バイセクシュアル(bisexual)・ノンバイナリー(non-binary)で、自由・オープンソースソフトウェア(F/OSS)とフェディバース(fediverse)の熱烈な支持者です。

STF(@sovtechfund)の支援を受け、TypeScript用ActivityPubサーバーフレームワーク「@fedify」の開発に専念しています。他にも、おひとり様向けのActivityPubマイクロブログ「@hollo」、ActivityPubボットフレームワーク「@botkit」、ソフトウェア開発者向けフェディバースプラットフォームHackers' Pub、JavaScript・TypeScript用ロギングライブラリLogTapeなどの制作者でもあります。

東アジア言語(いわゆるCJK)とUnicodeにも興味があります。このアカウントでは主に英語で投稿していますが、時々日本語や国漢文混用体(漢字ハングル混じり文)の韓国語でも書いています。実はこの文体で書きたくてフェディバースを始めた、という経緯もあります。日本語、英語、韓国語、漢文でも気軽に話しかけてください!

speakerdeck.com

国漢文混用体からHolloまで

本発表では、韓国語の「国漢文混用体」(漢字ハングル混じり文)を自分のフェディバース投稿に実装したいという小さな目標から始まった旅路を共有します。 この目標を達成するために、ActivityPubのJSON-LDの複雑さやHTTP Signatures、WebFingerなどの仕様を理解する必要性に…

Pinned

安寧(안녕)하세요! 저는 서울에 살고 있는 30() 後半(후반)의 오픈 소스 소프트웨어 엔지니어 洪民憙(홍민희)입니다. 兩性愛者(양성애자)(bisexual)이자 논바이너리(non-binary)이며, 自由(자유)·오픈 소스 소프트웨어(F/OSS)와 聯合宇宙(연합우주)(fediverse)의 熱烈(열렬)支持者(지지자)이기도 합니다.

STF(@sovtechfund)의 支援(지원)을 받아 TypeScript() ActivityPub 서버 프레임워크 @fedify 開發(개발)專業(전업)으로 ()하고 있습니다. 그 ()에도 싱글 유저() ActivityPub 마이크로블로그 @hollo, ActivityPub 봇 프레임워크 @botkit, 소프트웨어 開發者(개발자)를 위한 聯合宇宙(연합우주) 플랫폼 Hackers' Pub, JavaScript·TypeScript() 로깅 라이브러리 LogTape ()製作者(제작자)이기도 합니다.

()아시아 言語(언어)(이른바 CJK)와 Unicode에도 關心(관심)이 많습니다. 이 計定(계정)에서는 ()英語(영어)로 포스팅하지만, 때때로 日本語(일본어)國漢文混用體(국한문 혼용체) 韓國語(한국어)로도 씁니다. 聯合宇宙(연합우주)에 오게 된 動機(동기) () 하나가 바로 國漢文混用體(국한문 혼용체)로 글을 쓰고 싶었기 때문이기도 하고요. 韓國語(한국어), 英語(영어), 日本語(일본어), 아니면 漢文(한문)으로도 말을 걸어주세요!

logtape.org

LogTape

Unobtrusive logging library with zero dependencies—library-first design for Deno, Node.js, Bun, browsers, and edge functions

@botwiki@mastodon.social · Reply to 洪 民憙 (Hong Minhee) :nonbinary:

FedifyベースのBotKitという名前のフェディバースボットを作成する為のフレームワークをブレーンストーミングしています。Fedifyより柔軟性は劣りますが、より短いコードで簡単なフェディバースボットを作成できる様にするのが目標です。どう思いますか?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text

import { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;

Fedify 基盤(기반)의 BotKit이라는 이름의 聯合宇宙(연합우주)(fediverse) 봇을 만드는 프레임워크를 브레인스토밍해보고 있어요. Fedify보다 柔軟性(유연성)은 떨어질테지만, 그래도 훨씬 짧은 코드로 簡單(간단)聯合宇宙(연합우주) 봇을 만들 수 있게 하는 게 目標(목표)입니다. 어떻게들 보시나요?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text

import { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text

import { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;

@yeokbo@uri.life

항공기 사고를 주로 다루는 유튜버 ’다큐9분‘의 코멘트. 참고가 되는 부분이 있어 소개.

> 수십년 분의 항공사고 보고서와 기사를 보며 느낀 것이 있습니다.

> 1. 속보 경쟁을 할 필요가 없습니다. 지난 항공 사고 뉴스를 보면 정말 어처구니 없는 속보가 대부분입니다. 초기에는 오보가 정말 많습니다. 목격담도 대부분 착각입니다. 오보도 굳이 알 필요가 없는 부수적인 것입니다. 궁금한 것이 많겠지만, 지금 단계에서는 모두 추측입니다. 가십거리로 소비하면 안 됩니다.

> 2. 피해 가족에 대한 지원이 필요합니다. 지금 무안으로 피해자 가족들이 급한 마음으로 내려가고 있을 겁니다. 대부분의 사고에서 이 분들은 방치되어 2차적인 피해를 입습니다. 정부도 피해자 가족에 대한 지원을 해야하지만, 시민들도 이 분들을 도와야 합니다. 댓글 하나를 쓸 때도 잠깐 고민하길 바랍니다.

> 3. 희생자들의 존엄성을 지켜줘야 합니다. 희생자들의 존엄성을 무시한 사진과 보도들이 퍼지는 경우가 많습니다. 끔찍한 사고 현장이 뉴스 가치가 있을 수 있지만, 언론들은 윤리준칙에 따라 엄중하게 보도해야 합니다. 다시 한번 말하지만 가십거리로 소비되면 안 됩니다.

> 4. 책임자를 빨리 잡아낼 이유가 없습니다. 책임자가 빨리 드러난다고 더 안전해지는 것이 아닙니다. 누군가의 악의로 사고가 일어나지 않습니다. 차분히 지켜보며, 피해자를 돕고, 다시 같은 일이 일어나지 않게 철저히 조사하는 것이 사고의 상처를 빨리 수습하는 길이 될 것입니다.

> 지금도 목숨을 걸고 구조작업을 하고 있을 구조대를 응원합니다.

m.youtube.com/post/UgkxlyK2mnm

youtube.com

다큐9분님의 게시물

수십년 분의 항공사고 보고서와 기사를 보며 느낀 것이 있습니다. 1. 속보 경쟁을 할 필요가 없습니다. 지난 항공 사고 뉴스를 보면 정말 어처구니 없는 속보가 대부분입니다. 초기에는 오보가 정말 많습니다. 목격담도 대부분 착각입니다. 오보도 굳이 알 필요가 없는 부수적인 것입니다....

FedifyベースのBotKitという名前のフェディバースボットを作成する為のフレームワークをブレーンストーミングしています。Fedifyより柔軟性は劣りますが、より短いコードで簡単なフェディバースボットを作成できる様にするのが目標です。どう思いますか?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text

import { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;

Fedify 基盤(기반)의 BotKit이라는 이름의 聯合宇宙(연합우주)(fediverse) 봇을 만드는 프레임워크를 브레인스토밍해보고 있어요. Fedify보다 柔軟性(유연성)은 떨어질테지만, 그래도 훨씬 짧은 코드로 簡單(간단)聯合宇宙(연합우주) 봇을 만들 수 있게 하는 게 目標(목표)입니다. 어떻게들 보시나요?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text

import { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;

@hongminhee@hollo.social

I'm currently brainstorming a framework for creating fediverse bots called , based on . It's less flexible than Fedify, but the goal is to make it possible to create simple fediverse bots with much less code. What do you think?

import { createBot, mention, text } from "@fedify/botkit";
import { RedisKvStore } from "@fedify/redis";
import { Redis } from "ioredis";

// Create a bot instance:
const bot = createBot({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  bio: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social").}`,
  // Use Redis as a key-value store:
  kv: new RedisKvStore(new Redis()),
  // Use Redis as a message queue:
  queue: new RedisMessageQueue(() => new Redis()),
});

// A bot can respond to a mention:
bot.on(/hi|hello|what'?s\s+up/i, (ctx) => {
  return ctx.reply(text`Hi, ${ctx.actor}!`);
});

// Or, a bot also can actively publish a post:
setInterval(async () => {
  await bot.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text

import { createBot, mention, text } from "@fedify/botkit"; import { RedisKvStore } from "@fedify/redis"; import { Redis } from "ioredis"; // Create a bot instance: const bot = createBot({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: bio: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social").}`, // Use Redis as a key-value store: kv: new RedisKvStore(new Redis()), // Use Redis as a message queue: queue: new RedisMessageQueue(() => new Redis()), }); // A bot can respond to a mention: bot.on(/hi|hello|what'?s\s+up/i, (ctx) => { return ctx.reply(text`Hi, ${ctx.actor}!`); }); // Or, a bot also can actively publish a post: setInterval(async () => { await bot.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;

@nhk@phalanstere.social
@news_society@802.3ether.net
@intmonitor@mastodon.social

At least 28 people were dead after an airliner went off the runway and crashed at South Korea's Muan International Airport, Yonhap news agency reported.

The accident occurred as the Jeju Air plane, carrying 175 passengers and six crew on a flight from Thailand, was landing at the airport.

Firefighters carry out extinguishing operations on an aircraft which drove off runaway at Muan International Airport in Muan, South Jeolla Province, South Korea
ALT text

Firefighters carry out extinguishing operations on an aircraft which drove off runaway at Muan International Airport in Muan, South Jeolla Province, South Korea

@EUCommission@ec.social-network.europa.eu

Today is the day. Welcome to THE charger!

USB-C is officially the common standard for charging electronic devices in the EU.

This means:

🔌The same charger for all new phones, tablets and cameras
⚡ Harmonised fast-charging technology
🔄 Reduced e-waste
🛑 No more “Sorry, I don’t have the right cable”

One charger to rule them all.

A minimalist illustration showing a packaged charger box labeled "one Union one Charger." The box features an image of a blue charger with the European Union flag symbol and a USB-C cable. The scene is set within a holiday theme, with decorative Christmas trees, ornaments, and gift boxes surrounding the charger box. In the top right corner, there is a small EU flag symbol.
ALT text

A minimalist illustration showing a packaged charger box labeled "one Union one Charger." The box features an image of a blue charger with the European Union flag symbol and a USB-C cable. The scene is set within a holiday theme, with decorative Christmas trees, ornaments, and gift boxes surrounding the charger box. In the top right corner, there is a small EU flag symbol.

@parksb@silicon.moe · Reply to Simon Park

htmx가 그저 SPA나 자바스크립트에 대한 환멸감으로 나온 밈 수준이라고 생각하지는 않는다. 특히 나는 하이퍼미디어에 대한 이 정도로 진지한 고찰을 REST 이후로 처음 접해보는 것 같다. 복잡한 상태를 관리해야 웹 앱에는 하이퍼미디어 시스템이 어울리지 않겠지만(저자들도 이런 한계를 언급한다.), '비선형적 탐색이 가능한 매체'로서 웹을 사용하고자 한다면 하이퍼미디어는 여전히 최고의 아이디어라고 생각한다.

@kodingwarrior@silicon.moe

이번에 만드는 중인 플러터 기반의 페디버스 앱은... HTML를 화면에다가 그리는게 좀 빡센 일이었는데 어째저째 잘 되긴 했다.

dart에 html 파서가 다행히 있어서 파싱트리를 만드는 일 자체는 어렵지 않았다. 이젠 렌더러를 정확하게 구현하는게 문제... 일단 돌아는 가는 코드를 짜긴 했다만 테스트 코드를 짜는 전략은 어떻게 들고가는게 좋을까...

@hollo@hollo.social

One hidden feature of : You can also quote another post while replying to someone else's post.