Skip to content

feat(moa): add Album (Moa) REST service - #214

Open
enkunkun wants to merge 1 commit into
evex-dev:mainfrom
enkunkun:feat/moa-album-service
Open

feat(moa): add Album (Moa) REST service#214
enkunkun wants to merge 1 commit into
evex-dev:mainfrom
enkunkun:feat/moa-album-service

Conversation

@enkunkun

Copy link
Copy Markdown
Contributor

Description

Adds MoaService, wired up as client.base.moa, exposing the LINE Album
(Moa) subsystem. This subsystem was previously unreachable through LINEJS —
users had to hand-craft HTTP requests against the LEGY proxy to list albums
or download original photos.

Unlike Talk / Square, Moa is plain HTTP JSON on top of the LEGY proxy,
not Thrift, so this service uses client.fetch directly with an
X-Line-ChannelToken issued via
channel.approveChannelAndIssueChannelToken({channelId: "1375220249"}).

API

// List all albums (paginate via cursor)
const resp = await client.base.moa.getAlbums({ cursor: "" });
for (const album of resp.result?.albums ?? []) {
  console.log(album.title, album.photoCount);
}

// List photos in an album
const photos = await client.base.moa.getPhotos({
  chatId, albumId, cursor: "", pageSize: 100,
});

// Download original bytes (image or video)
const bytes = await client.base.moa.downloadPhoto({
  chatId, albumId, oid: photo.obsResourceId!.oid!,
  prefix: photo.obsResourceId?.sid === "v" ? "album/v" : "album/a",
});

buildMoaUrl is exported as a pure helper for anyone wanting to hand-craft
additional Moa endpoints (the AB service in CHRLINE covers ~30 more).

Header override caveat

The Moa REST endpoints require accept: application/json. The default
client.base.request.getHeader("GET") returns
accept: application/x-thrift, which causes LEGY to reject Moa requests
with {"code":102001,"message":"一時的なエラーが発生しました。"} at HTTP 200.
MoaService handles this override internally.

What changed

  • packages/linejs/base/service/moa/mod.ts (new) — MoaService +
    buildMoaUrl helper + response type interfaces.
  • packages/linejs/base/service/moa/mod.test.ts (new) — 5 tests
    covering buildMoaUrl edge cases (custom endpoint, encoding, undefined
    skipping).
  • packages/linejs/base/service/mod.ts — re-export MoaService.
  • packages/linejs/base/core/mod.ts — register
    client.moa = new MoaService(this) alongside other services.
  • docs/docs/moa.md (new) + sidebar entry — usage examples and the
    Accept-header caveat.

Verified end-to-end

Against a live LINE account:

  • getAlbums({}) returned 100 albums (first page)
  • getPhotos({chatId, albumId}) returned photo metadata with
    obsResourceId, shotTime, etc.
  • downloadPhoto({...oid}) returned the original JPEG (245 KB) matching
    the LINE app's saved copy byte-for-byte

Checklist

  • MoaService verified against live LINE (list + list-photos + download)
  • Unit tests for buildMoaUrl (5 cases)
  • Documentation page + sidebar link
  • Follows existing service registration pattern in BaseClient

Exposes the LINE Album subsystem as `client.base.moa`. Unlike Talk / Square,
Moa is a plain HTTP JSON API on top of the LEGY proxy — not Thrift — so this
service uses `client.fetch` directly with an `X-Line-ChannelToken` obtained
from `channel.approveChannelAndIssueChannelToken({channelId: "1375220249"})`.

- packages/linejs/base/service/moa/mod.ts: MoaService with
    getAlbumChannelToken() — memoised channel-token issuance for 1375220249
    getAlbums({cursor, orderBy, include}) — paginated album list
    getPhotos({chatId, albumId, cursor, pageSize, ...}) — paginated photos
    downloadPhoto({chatId, albumId, oid, prefix?}) — original bytes (Uint8Array)
  All requests override the linejs default headers with
  `accept: application/json` and `content-type: application/json; charset=UTF-8`,
  otherwise LEGY replies with
  `{"code":102001,"message":"一時的なエラーが発生しました。"}` at HTTP 200.
  buildMoaUrl is exported as a pure helper so users writing custom Moa calls
  can reuse the URL encoding.
- packages/linejs/base/service/moa/mod.test.ts: 5 tests covering buildMoaUrl
  edge cases (endpoint, encoding, undefined skipping, custom host).
- packages/linejs/base/service/mod.ts: re-export MoaService.
- packages/linejs/base/core/mod.ts: register `client.moa = new MoaService(this)`
  alongside the other services.
- docs/docs/moa.md + config.mts sidebar entry: usage examples and the header
  override note.

Verified end-to-end against a live LINE account: getAlbums returns 100
albums, getPhotos returns photo metadata with obsResourceId, and
downloadPhoto returns the original JPEG bytes (245 KB for a sample image).
@enkunkun
enkunkun force-pushed the feat/moa-album-service branch from 1b055f0 to bdfe21a Compare July 23, 2026 01:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant