LoginSignup
5
7

More than 5 years have passed since last update.

slackに長すぎるメッセージを投稿すると、メッセージが自動的に分割されるようになっていた

Last updated at Posted at 2018-03-19

昔は413 Payload Too Largeが返されていたが、今は受け付けてくれる。
413が返されるのは去年の夏くらいに確認したが、その後いつ変更されたんだろうか。

自動分割された場合はレスポンスにis_auto_splitフィールドが増える。
is_auto_splitフィールドは、自動分割されなかった場合は存在しない(falseになるわけではない)ので注意が必要である。
また、自動分割された場合のレスポンスのmessage.textフィールドは、分割された一連メッセージのうち、最後のメッセージのテキストとなり、全文は含まれない。

{
  "ok": true,
  "ts": "1521494094.000437",
  "message": {
    "text": "分割された一連のメッセージのうち、最後のメッセージのテキスト",
    "username": "Slack API Tester",
    "is_auto_split": true,
    "type": "message",
    "subtype": "bot_message",
    "ts": "1521494094.000437"
  },
  "warning": "missing_charset",
  "response_metadata": {
    "warnings": [
      "missing_charset"
    ]
  }
}

何文字で分割されるのかは仕様が見当たらなかった。
実測によると4042文字である。

# coding: utf_8
import bisect
import json
import time
import requests


TOKEN = ''


def json_post(char, length):
    time.sleep(3)
    h = {
            'Content-type': 'application/json',
            'Authorization': 'Bearer ' + TOKEN,
        }
    d = json.dumps({
            'channel': 'general',
            'text': ''.join([char] * length),
        })
    r = requests.post('https://slack.com/api/chat.postMessage', headers=h, data=d)
    if not r.json()['ok']:
        raise Exception()
    return 1 if r.json().get('message', {}).get('is_auto_split') else 0


def form_post(char, length):
    time.sleep(3)
    d = {
            'token': TOKEN,
            'channel': 'general',
            'text': ''.join([char] * length),
        }
    r = requests.post('https://slack.com/api/chat.postMessage', data=d)
    if not r.json()['ok']:
        raise Exception()
    return 1 if r.json().get('message', {}).get('is_auto_split') else 0


class Resolver(object):

    def __init__(self, char, post):
        self.char = char
        self.post = post

    def __len__(self):
        return 100000

    def __getitem__(self, key):
        return self.post(self.char, key)


print(bisect.bisect(Resolver('a', json_post), 0))
print(bisect.bisect(Resolver('あ', json_post), 0))
print(bisect.bisect(Resolver('a', form_post), 0))
print(bisect.bisect(Resolver('あ', form_post), 0))
$ pipenv run python _.py
4041
4041
4041
4041

aを個別にチェックしているのは昔の名残である。
以前のSlackはパーセントエンコード後のバイト数で文字数をカウントしていたため、9文字扱いだった(utf8で3バイト、パーセントエンコード後9バイト)のだ。
今はそういうことはないようだ。

5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7