はじめに
SlackからGoogle Chatへの移行を検討している方、Slackで長年蓄積したカスタム絵文字をGoogle Chatでも使いたいと思ったことはありませんか?
弊社でもGoogle Chatを利用することが増えてきたのでSlackのようにカスタム絵文字を使いたい!というニーズが高まってきました。
今回、Slackからエクスポートした絵文字をGoogle Chat APIを使って一括登録するPythonツールを作成しました。約3,800件の絵文字を一括登録した実践記録とともに紹介します。
ただし、組織外のメンバーがいるスペースでは使えないみたいです、残念...
完成したツール
GitHub: google-chat-emoji-bulk-uploader
主な機能
- Slackエクスポートの絵文字画像を自動検出
- Google Chat APIの制約に基づく自動バリデーション
- エラーファイルをカテゴリ別にフォルダ分け
- 既存の絵文字はスキップ(重複防止)
Google Chat 絵文字の制約
Google Chatのカスタム絵文字には以下の制約があります:
| 項目 | 制約 |
|---|---|
| ファイルサイズ | 256KB以下 |
| 寸法 | 64px〜500pxの正方形 |
| 形式 | PNG, JPG, GIF |
| 命名規則 | 小文字英数字、ハイフン、アンダースコアのみ |
セットアップ手順
1. Google Cloud Console での設定
プロジェクト作成とAPI有効化
- Google Cloud Console にアクセス
- 新しいプロジェクトを作成(例:
emoji-bulk-uploader) - 「APIとサービス」→「ライブラリ」で Google Chat API を検索して有効化
OAuth同意画面の設定
- 「APIとサービス」→「OAuth同意画面」
- ユーザータイプ: 内部(組織内のみ)または外部
- スコープを追加:
https://www.googleapis.com/auth/chat.customemojis
OAuth認証情報の作成
- 「APIとサービス」→「認証情報」→「認証情報を作成」
- 「OAuthクライアントID」を選択
- アプリケーションの種類: デスクトップアプリ
- 作成後、JSONをダウンロードして
credentials.jsonとして保存
Chat アプリの設定(重要!)
これが最初のハマりポイントでした。OAuth認証情報だけでは不十分で、Chat APIの構成設定が必要です。
- Google Cloud Console → 「Google Chat API」→「構成」タブ
- 以下を設定(アバターURLと説明は必須):
- アプリ名
- アバターURL(任意の画像URLでOK)
- 説明
これを設定しないと Google Chat app not found エラーが発生します。
2. 依存関係のインストール
pip install -r requirements.txt
必要なパッケージ:
google-auth-oauthlibgoogle-api-python-clientPillow
使い方
基本的な使い方
# emojis/ ディレクトリの絵文字をアップロード
python main.py emojis/
初回実行時にブラウザが開き、Googleアカウントでの認証を求められます。
ドライラン(検証のみ)
python main.py emojis/ --dry-run
アップロード前にバリデーションエラーを確認できます。
エラーファイルの分類
python main.py emojis/ --organize-errors errors/
エラーファイルがカテゴリ別にフォルダ分けされます:
errors/
├── invalid_dimension/ # サイズが64-500px範囲外
├── invalid_format/ # PNG/JPEG/GIF以外の形式
├── not_square/ # 正方形でない画像
└── upload_errors/ # アップロード時のAPIエラー
├── invalid_payload/ # GIFエンコード問題
├── reserved_name/ # 予約語・禁止ワード
└── invalid_name_api/ # APIが拒否した無効な名前
実践:3,800件の絵文字を一括登録
結果サマリー
| 項目 | 件数 |
|---|---|
| 総ファイル数 | 3,818 |
| バリデーション通過 | 3,643 |
| アップロード成功 | 3,574 |
| アップロード失敗 | 42 |
成功率: 約99%
バリデーションエラーの内訳(175件)
| カテゴリ | 件数 | 説明 |
|---|---|---|
| not_square | 113 | 正方形でない画像 |
| invalid_dimension | 55 | サイズが64-500px範囲外 |
| invalid_format | 7 | PNG/JPEG/GIF以外の形式 |
アップロードエラーの内訳(42件)
| カテゴリ | 件数 | 説明 |
|---|---|---|
| invalid_payload | 14 | GIFエンコード問題 |
| reserved_name | 10 | 予約語・禁止ワード |
| invalid_name_api | 10 | 末尾特殊文字、1文字の名前 |
| name_too_long | 1 | 名前が長すぎる |
開発中にハマったポイント
1. Chat アプリの設定が必要
OAuth認証情報を作成しただけでは動きません。Google Chat APIの「構成」タブでアプリ設定(アバターURL、説明)が必須です。
エラー:
Google Chat app not found
解決: Cloud Console → Chat API → 構成 でアプリ設定を完了する
2. 絵文字名にはコロンが必要
APIに送信する絵文字名は :emoji-name: の形式(前後にコロン)が必要です。
エラー:
Duplicate or malformed custom emoji name
解決:
emoji_name_with_colons = f':{emoji_name}:'
3. APIリクエストボディの形式
Google Chat API v1の形式に従う必要があります。
body = {
'emojiName': ':emoji-name:',
'payload': {
'fileContent': base64_encoded_image,
'filename': 'emoji.png',
}
}
4. 予約語・禁止ワード
以下のような名前はAPIで拒否されます:
- 予約語:
atom,biohazard,skip,jojo,koronaなど - 1文字の名前:
e,n,p,s,w,y - 末尾特殊文字:
are-_,kaneda-_ - 長すぎる名前
これらはバリデーション時点では検出できず、API呼び出し時に初めてエラーになります。
5. 一部のGIFが処理できない
アニメーションGIFの一部はAPIで Invalid payload エラーになります。おそらくGIFのエンコード形式やフレーム数の問題です。
回避策:
- PNGに変換する
- ffmpegで再エンコードする
コードのポイント
バリデーション
def validate_emoji(file_path: str) -> ValidationResult:
# 名前のバリデーション
if not re.match(r'^[a-z0-9_-]+$', emoji_name):
errors.append("Invalid name")
# 画像のバリデーション
with Image.open(file_path) as img:
if img.format not in {'PNG', 'JPEG', 'GIF'}:
errors.append("Invalid format")
if img.size[0] != img.size[1]:
errors.append("Not square")
アップロード
def upload_emoji(self, file_path: str, emoji_name: str) -> UploadResult:
image_data = base64.standard_b64encode(open(file_path, 'rb').read()).decode('utf-8')
body = {
'emojiName': f':{emoji_name}:',
'payload': {
'fileContent': image_data,
'filename': Path(file_path).name,
}
}
result = self.service.customEmojis().create(body=body).execute()
既存絵文字のスキップ
def list_existing_emojis(self) -> set[str]:
existing = set()
page_token = None
while True:
response = self.service.customEmojis().list(
pageSize=100, pageToken=page_token
).execute()
for emoji in response.get('customEmojis', []):
name = emoji.get('emojiName', '').strip(':')
existing.add(name)
if not response.get('nextPageToken'):
break
return existing
まとめ
Google Chat APIを使ってSlackの絵文字を一括移行するツールを作成しました。約3,800件中3,574件(99%)の移行に成功しました。
主なハマりポイント:
- Chat アプリの設定が必須(アバターURL、説明)
- 絵文字名はコロンで囲む
- 予約語や特殊な名前はAPIで拒否される
- 一部のGIFは処理できない
このツールを使えば、大量の絵文字も効率的に移行できます。SlackからGoogle Chatへの移行を検討している方の参考になれば幸いです。

