npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@msgly/line

v0.2.2

Published

LINE Messaging API adapter for Msgly

Downloads

61

Readme

@msgly/line

LINE Messaging API adapter for Msgly. Send and receive LINE messages through the unified hub — text, image, video, audio, location, buttons, and quick replies. Supports LINE's free reply-token sends. Zero classes, runs in Node, Next.js, and Edge runtimes.

Install

npm install @msgly/core @msgly/line

Quick start

import express from 'express';
import { createHub } from '@msgly/core';
import { createLineAdapter } from '@msgly/line';

const hub = createHub();

hub.register(
  createLineAdapter({
    channelAccessToken: process.env.LINE_CHANNEL_ACCESS_TOKEN!,
    channelSecret: process.env.LINE_CHANNEL_SECRET!,
  }),
);

await hub.connect({ throwOnFailure: true });

hub.on('message', async (msg) => {
  if (msg.channel === 'line' && msg.content.type === 'text') {
    // Use the free reply token when available
    await hub.send({
      channel: 'line',
      account: msg.account,
      contact: msg.contact,
      content: { type: 'text', text: `You said: ${msg.content.text}` },
      metadata: { replyToken: msg.metadata?.replyToken },
    });
  }
});

const app = express();
app.use(express.json({ verify: (req, _r, buf) => ((req as any).rawBody = new Uint8Array(buf)) }));

const handlers = hub.createWebhookHandler();
app.get('/webhook/:channel', handlers.get);
app.post('/webhook/:channel', handlers.post);

app.listen(3000);

Config

interface LineConfig {
  /** Long-lived channel access token from the Messaging API tab. */
  channelAccessToken: string;

  /** Channel secret from Basic settings — used for webhook signature verification. */
  channelSecret: string;

  /** Override for tests. Defaults to https://api.line.me */
  apiBase?: string;

  /** Override for tests. Defaults to https://api-data.line.me (media endpoints). */
  dataApiBase?: string;
}

Setup (10 minutes)

  1. Sign up at developers.line.biz. Create a Provider, then a Messaging API channel inside it.
  2. Channel secret. Open the channel → Basic settings → copy Channel secret → set as LINE_CHANNEL_SECRET.
  3. Channel access token. Messaging API tab → under "Channel access token (long-lived)" click Issue → copy → set as LINE_CHANNEL_ACCESS_TOKEN.
  4. Webhook URL. On the Messaging API tab:
    • Webhook URL: <PUBLIC_URL>/webhook/line
    • Toggle Use webhook to ON
    • Click Verify — should succeed
  5. Disable LINE's built-in replies. Same tab:
    • "Auto-reply messages": OFF (otherwise LINE answers before your bot)
    • "Greeting messages": OFF (optional)
  6. Add the bot to a chat. Find the bot's QR code on the Messaging API tab → scan with the LINE app → add as friend → message it.

Capabilities

| Feature | Supported | | ------------- | --------- | | text | ✓ | | image | ✓ | | video | ✓ | | audio | ✓ | | file | — | | location | ✓ | | buttons | ✓ | | quick replies | ✓ (max 13, 20-char labels) | | templates | — | | reactions | — | | typing | — |

Reply tokens (free vs push)

LINE's pricing model:

  • Reply API (uses a replyToken from the inbound event) — free, doesn't count against your monthly quota.
  • Push API (no reply token) — counts against your push quota.

Reply tokens are single-use and expire about 1 minute after the inbound message. Use them when responding immediately:

hub.on('message', async (msg) => {
  if (msg.channel === 'line' && msg.content.type === 'text') {
    await hub.send({
      channel: 'line',
      account: msg.account,
      contact: msg.contact,
      content: { type: 'text', text: 'thanks!' },
      metadata: { replyToken: msg.metadata?.replyToken },  // ← free reply
    });
  }
});

Send without replyToken and the adapter falls back to push automatically.

Sending examples

Image

await hub.send({
  channel: 'line',
  account, contact,
  content: {
    type: 'image',
    mediaRef: { kind: 'url', value: 'https://example.com/cat.jpg' },
  },
});

LINE requires media URLs to be public HTTPS with no auth.

Quick replies

await hub.send({
  channel: 'line',
  account, contact,
  content: {
    type: 'interactive',
    text: 'Pick one:',
    buttons: [
      { id: 'a', label: 'Option A' },
      { id: 'b', label: 'Option B' },
    ],
  },
});

User tap → you receive a text message whose content.text matches the button id.

Common pitfalls

  • Bot replies but user doesn't see it: in the LINE Developers Console, "Auto-reply messages" must be OFF. It overrides your bot's responses.
  • Invalid reply token: the token expired (>1 min) or was already used. Fall back to push by omitting metadata.replyToken.
  • InvalidSignature: LINE_CHANNEL_SECRET is wrong, or your Express app isn't capturing the raw body. The verify callback in express.json() is essential.
  • Webhook verify fails in console: server must be running and reachable at the public URL when you click Verify.

Documentation

Full setup walkthrough and multi-channel usage: https://github.com/AyushJain070401/msgly

License

MIT