Skip to main content

Async Python client for Sakamichi Group Message API (Nogizaka46, Sakurazaka46, Hinatazaka46)

Project description

pysaka

PyPI version License: MIT

Build Status

Disclaimer & Warnings

[!CAUTION] Use at your own risk. accessing the API via unauthorized means may violate the Terms of Service of the respective platforms. This library is for educational purposes only.

規約 / Terms of Service Ref.

Users must agree to the official Terms of Service of the respective platforms. The following are excerpts from the official terms (as of writing):

第3条(知的財産権)/ Article 3 (Intellectual Property)

  1. 当社が別に定める場合を除き、お客様が本コンテンツを複製、翻案、頒布、公衆送信等することは禁止します。

第8条(禁止事項)/ Article 8 (Prohibited Acts)

(11) 当社または第三者の情報、データおよびソフトウェアを修正、改変、改ざん、リバースエンジニアリング、逆コンパイル、逆アッセンブルまたは消去等する行為

(16) 当社が指定するアクセス方法以外の手段で本サービスにアクセスし、またはアクセスを試みる行為

(17) 自動化された手段(クローラおよび類似の技術を含む)を用いて本サービスにアクセスし、またはアクセスを試みる行為

Async Python client for Sakamichi Groups (Nogizaka46, Sakurazaka46, Hinatazaka46, Yodel) Message API.

pysaka provides a robust, type-hinted, and async interface to interact with the official Message apps for all supported groups. It handles authentication (via browser), token management, and data retrieval.

Features

  • 🔐 Browser Authentication: Seamless interactive login via Playwright (compatible with MFA/SSO).
  • 🍪 Auto-Refresh: Automatically refreshes access tokens using captured cookies.
  • 🚀 Async/Await: Built on aiohttp for high-performance concurrent requests.
  • 📦 Multi-Group: Supports Nogizaka46, Sakurazaka46, Hinatazaka46, and Yodel out of the box.
  • 📝 Blog Scraper: Backup official blogs (HTML + images) for all three groups.
  • 🛠️ Type Hinted: 100% type coverage for better IDE support.

Configuration

pysaka uses structlog for observability. You can control the logging output via environment variables:

  • HAKO_ENV=development (default): Pretty-printed, colored console logs.
  • HAKO_ENV=production: Structured JSON logs with automatic secret redaction.

Installation

Recommended install via uv:

uv add pysaka

For development:

git clone https://github.com/xebjhm/pysaka.git
cd pysaka
uv sync

Quick Start

1. Authentication

Use BrowserAuth to log in interactively. This launches a browser window for you to enter credentials.

import asyncio
from pysaka import BrowserAuth, Group

async def login():
    creds = await BrowserAuth.login(Group.NOGIZAKA46)
    print(creds['access_token'])

asyncio.run(login())

2. Fetching Data

Initialize the Client with your credentials.

import asyncio
import aiohttp
from pysaka import Client, Group

async def main():
    # ... assume creds obtained via BrowserAuth ...
    token = "YOUR_ACCESS_TOKEN"

    async with aiohttp.ClientSession() as session:
        client = Client(Group.NOGIZAKA46, access_token=token)

        # Get Profile
        profile = await client.get_profile(session)
        print(f"Hello, {profile['nickname']}!")

        # Get Groups (Members)
        groups = await client.get_groups(session)
        for g in groups:
            print(f"{g['name']} (ID: {g['id']})")

asyncio.run(main())

3. Blog Scraping (No Auth Required)

Scrape official blogs for any group without authentication.

import asyncio
import aiohttp
from pysaka.blog import NogizakaBlogScraper, HinatazakaBlogScraper, SakurazakaBlogScraper

async def scrape_blogs():
    async with aiohttp.ClientSession() as session:
        scraper = NogizakaBlogScraper(session)

        # Get all active members
        members = await scraper.get_members()
        print(f"Found {len(members)} members")

        # Get blogs for a specific member
        async for blog in scraper.get_blogs(member_id="some_member_code"):
            print(f"{blog.title} - {blog.published_at}")

asyncio.run(scrape_blogs())

API Reference

Client

The main entry point.

  • __init__(group, access_token, ...): Initialize client.
  • get_profile(session): Get current user profile.
  • get_groups(session): List subscribed members/groups.
  • get_messages(session, group_id, ...): Fetch messages timeline.
  • get_news(session): Fetch official announcements.
  • get_tags(session): Fetch tags.
  • get_fc_contents(session): Fetch Fan Club content.
  • get_organizations(session): Fetch organizations.
  • get_products(session, product_type): Fetch products (subscriptions).
  • post_json(session, endpoint, data): Perform JSON POST requests.
  • delete_json(session, endpoint): Perform DELETE requests.
  • download_file(session, url, filepath): Download a file to local filesystem.
  • get_member(session, member_id): Fetch individual member details.
  • get_account(session): Fetch user account information.
  • get_letters(session, group_id): Fetch user's sent letters/cards.
  • get_past_messages(session, group_id): Fetch historical messages.
  • get_subscription_streak(session, group_id): Fetch consecutive subscription days.
  • add_favorite(session, message_id): Add a message to favorites.
  • remove_favorite(session, message_id): Remove a message from favorites.
  • refresh_if_needed(session): Lazy token refresh if expiring soon.

Credential Management

  • get_token_manager(): Get the singleton TokenManager instance for secure credential storage.
  • TokenManager.save_session(group, access_token, ...): Save session credentials to system keyring.
  • TokenManager.load_session(group): Load stored session credentials.
  • TokenManager.delete_session(group): Remove stored credentials.

BrowserAuth

Helper for OAuth2 flow.

  • login(group, headless=False, ...): Perform login and capture tokens.

Blog Scrapers

Public blog scrapers (no authentication required).

  • NogizakaBlogScraper(session): Nogizaka46 official blog.
  • SakurazakaBlogScraper(session): Sakurazaka46 official blog.
  • HinatazakaBlogScraper(session): Hinatazaka46 official blog.

Each scraper provides:

  • get_members(): Get dict of member_id -> member_name.
  • get_blogs(member_id, since_date=None): AsyncIterator of BlogEntry objects.
  • get_blog_detail(blog_id, member_id=None): Fetch single blog by ID.

Exceptions

  • SakaError: Base exception for all pysaka errors.
  • AuthError: Authentication related errors.
  • ApiError: API request errors (includes status_code attribute).
  • SessionExpiredError: Session invalidated server-side (e.g., logged in from another device).
  • RefreshFailedError: All token refresh attempts failed unexpectedly.
  • BlogGoneError: Blog post has been permanently removed (HTTP 404/410).

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for details.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pysaka-0.4.0.tar.gz (291.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pysaka-0.4.0-py3-none-any.whl (53.9 kB view details)

Uploaded Python 3

File details

Details for the file pysaka-0.4.0.tar.gz.

File metadata

  • Download URL: pysaka-0.4.0.tar.gz
  • Upload date:
  • Size: 291.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pysaka-0.4.0.tar.gz
Algorithm Hash digest
SHA256 4b35656b1d7ca51d4abd9250e6257f87b47cebf2c9a8bc9387ba2202e5eb25f7
MD5 d9b760254a58d445d2240dcd7c80d98a
BLAKE2b-256 9d12e3764ae7569faf40726d9ff7fa7793d921aef904ab1622e3b0b5caedc290

See more details on using hashes here.

Provenance

The following attestation bundles were made for pysaka-0.4.0.tar.gz:

Publisher: publish.yml on xebjhm/pysaka

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pysaka-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: pysaka-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 53.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pysaka-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 56191852967e1de6a832b8191c1ca0cf1a750f8ad89fcffd2b0c9deff779dd86
MD5 034d1e1ac49a87dbcd8e9e37b21101a5
BLAKE2b-256 bd6f9185cfb61a29760d1c433815baf79ae44bd2d723a8890c55b583d0927759

See more details on using hashes here.

Provenance

The following attestation bundles were made for pysaka-0.4.0-py3-none-any.whl:

Publisher: publish.yml on xebjhm/pysaka

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page