# EzLife · ឯកសារ Bot API

https://im-api.ez7.life/km/

បានធ្វើបច្ចុប្បន្នភាព: 2026-11-10

មគ្គុទ្ទេសក៍ BotMother សារ ការចម្លងលេខកូដ និងប៊ូតុងឆ្លើយតប។ ឧទាហរណ៍ប្រើតម្លៃគំរូ។

## ទិដ្ឋភាពទូទៅ និងសមត្ថភាព

វិធីសាស្ត្រសាធារណៈមាន `getMe`, `sendMessage`, `getUpdates`។ អាចផ្ញើអត្ថបទឯកជន/ក្រុម និងទទួលព្រឹត្តិការណ៍ដែលអាចមានមាតិកាមិនមែនអត្ថបទ។

ប្រើ `copy_text` ដើម្បីបង្ហាញរូបតំណាងចម្លងលេខកូដ និង `reply_markup` ដើម្បីដាក់ប៊ូតុងអត្ថបទក្រោមប្រអប់សរសេរសារឯកជន។

ដែននេះសម្រាប់ឯកសារ។ API នៅតែ im.ez7.life ក្រោម /bot-api/។ ចម្លង ID អ្នកទទួលនៅ ការកំណត់ → ព័ត៌មានគណនី → ID។ ឆ្លើយដោយ message.chat.id ដែលទទួល; ក្នុងព្រឹត្តិការណ៍ក្រុមវាជា ID ក្រុម។

```text
https://im.ez7.life/bot-api/<BOT_TOKEN>/<METHOD>
```

## ចាប់ផ្តើមរហ័ស

1. ស្វែងរក និងបន្ថែម `@BotMother` រួចបើកការគ្រប់គ្រងបូតនៅខាងលើការសន្ទនា។
2. បង្កើតបូត ចម្លង Token ហើយរក្សាក្នុងអថេរបរិស្ថានម៉ាស៊ីនមេ `EZLIFE_BOT_TOKEN`។
3. ហៅ `getMe` ដើម្បីផ្ទៀងផ្ទាត់ រួចហៅ `sendMessage` ជាមួយ ID អ្នកទទួល។
4. ទាញ `getUpdates` ជាប្រចាំ ហើយរក្សា offset បន្ទាប់តែក្រោយពេលដំណើរការជោគជ័យ។

```bash
python3 bot.py
```

## គ្រប់គ្រងតាម BotMother

ឈ្មោះបង្ហាញមាន 1–64 តួអក្សរ។ បុព្វបទគណនីក្នុងទម្រង់មាន 3–28 តួ ចាប់ផ្តើមដោយអក្សរអង់គ្លេស ប្រើតែអក្សរ លេខ និងគូសក្រោម។ ទម្រង់បន្ថែម `_bot`; ពិនិត្យឈ្មោះទំនេរមុនបង្កើត។

អាចស្វែងរកបូត មើល ID ស្ថានភាព ពេលបង្កើត និង `****` ជាមួយ 6 តួចុងក្រោយ Token ព្រមទាំងចេញថ្មី ឬដកហូត Token។ អ្នកគ្រប់គ្រងកំណត់ចំនួនបូតអតិបរមា។

| ពាក្យបញ្ជា | មុខងារ |
| --- | --- |
| `/start` | បង្ហាញការណែនាំគ្រប់គ្រង |
| `/newbot` | ចាប់ផ្តើមបង្កើតបូត |
| `/mybots` | បង្ហាញបូតរបស់អ្នក |
| `/token @username` | ចេញ Token ថ្មី ធ្វើឱ្យចាស់អស់សុពលភាព |
| `/revoke @username` | ដកហូត Token បច្ចុប្បន្ន |
| `/cancel` | បោះបង់ការបង្កើត |
| `/help` | បង្ហាញជំនួយ |

## Token និងសុវត្ថិភាព

Token ពេញបង្ហាញតែពេលបង្កើត ឬចេញថ្មី។ វាជាពាក្យសម្ងាត់បូត; ទុកនៅម៉ាស៊ីនមេ កុំដាក់ក្នុងគេហទំព័រ កម្មវិធី ឃ្លាំងសាធារណៈ ឬកំណត់ហេតុ។

ចេញថ្មីធ្វើឱ្យ Token ចាស់អស់សុពលភាពភ្លាម។ ដកហូតនឹងបិទការហៅពីក្រៅ។ តួចុងក្រោយដែលបិទបាំងមិនអាចស្ដារ Token បាន; បើបាត់ សូមចេញថ្មី និងកែកម្មវិធី។

Token ចាស់នឹងកត់ត្រាតួចុងក្រោយនៅការហៅ Bot API ត្រឹមត្រូវលើកបន្ទាប់។ API Token ក្នុងព័ត៌មានគណនីសម្រាប់ API គណនី; Bot API នេះប្រើ Token ពី BotMother។

## getMe · អត្តសញ្ញាណបូត

`POST https://im.ez7.life/bot-api/<BOT_TOKEN>/getMe`

មិនត្រូវការប៉ារ៉ាម៉ែត្រអាជីវកម្ម។ ត្រឡប់ ID បូត ឈ្មោះបង្ហាញ ឈ្មោះគណនី និងសញ្ញាសមត្ថភាពក្រុម។ ប្រើវាដើម្បីពិនិត្យ Token។

```bash
curl --fail-with-body --request POST \
  "https://im.ez7.life/bot-api/${EZLIFE_BOT_TOKEN}/getMe" \
  --header 'Content-Type: application/json' --data '{}'
```

```json
{
  "ok": true,
  "result": {
    "id": "1000000000",
    "is_bot": true,
    "display_name": "Example Bot",
    "username": "example_bot",
    "can_join_groups": true,
    "can_read_all_group_messages": true
  }
}
```

## sendMessage · ផ្ញើសារ

`POST https://im.ez7.life/bot-api/<BOT_TOKEN>/sendMessage`

ប្រើ `POST application/json`។ ផ្ញើ `chat_id` ជាខ្សែអក្សរជានិច្ច: ID អ្នកទទួលសម្រាប់ឯកជន ឬ ID ក្រុមជាមួយ `chat_type: "group"`។

អត្ថបទ 1–5000 តួ កាត់ចន្លោះដើមចុង។ រក្សា message_id ដែលទទួលបាន។ មិនមានកូនសោការពារផ្ញើស្ទួន; បើអស់ពេលរង់ចាំ សូមពិនិត្យលទ្ធផលមុនផ្ញើម្ដងទៀត។

| ប៉ារ៉ាម៉ែត្រ | ប្រភេទ | តម្រូវ | ការពិពណ៌នា |
| --- | --- | --- | --- |
| `chat_id` | string | បាទ/ចាស | ID អ្នកទទួល ឬ ID ក្រុម ជាខ្សែអក្សរជានិច្ច។ |
| `text` | string | បាទ/ចាស | អត្ថបទ 1–5000 តួ។ |
| `chat_type` | string | ទេ | លំនាំដើម private; ក្រុមប្រើ group ក៏ទទួល supergroup។ |
| `copy_text` | string | ទេ | ខ្សែអក្សរលេខ 4–12 ខ្ទង់បង្ហាញពេញក្នុង text។ |
| `reply_markup` | object / JSON string | ទេ | វត្ថុក្តារប៊ូតុង ឬខ្សែអក្សរ JSON មិនបង្ខំ។ |

```bash
curl --fail-with-body --request POST \
  "https://im.ez7.life/bot-api/${EZLIFE_BOT_TOKEN}/sendMessage" \
  --header 'Content-Type: application/json' --data-binary @- <<'JSON'
{
  "chat_id": "USER_ID",
  "text": "ការបញ្ជាទិញរបស់អ្នកបានដំណើរការហើយ។"
}
JSON
```

```json
{
  "chat_id": "GROUP_ID",
  "chat_type": "group",
  "text": "ការបញ្ជាទិញរបស់អ្នកបានដំណើរការហើយ។"
}
```

```json
{
  "ok": true,
  "result": {
    "message_id": "EXAMPLE_MESSAGE_ID",
    "date": 1794297600,
    "chat": {
      "id": "USER_ID",
      "type": "private"
    },
    "text": "ការបញ្ជាទិញរបស់អ្នកបានដំណើរការហើយ។"
  }
}
```

ផ្ញើជោគជ័យត្រឡប់ ok: true និង result, បន្ថែម copy_text សម្រាប់លេខកូដ និង reply_markup ជាមួយ reply_keyboard_revision សម្រាប់ម៉ឺនុយ។ ទទួលត្រឡប់អារេ result; គ្មានព្រឹត្តិការណ៍គឺ result: []។

## ចម្លងលេខកូដផ្ទៀងផ្ទាត់

ទុកឈ្មោះប្រព័ន្ធ គោលបំណង និងសុពលភាពក្នុងសារ រួចបន្ថែម copy_text ជាខ្សែអក្សរលេខ ASCII 4–12 ខ្ទង់ដែលបង្ហាញពេញក្នុង text។ ខ្សែអក្សររក្សាលេខសូន្យដើម។

រូបតំណាងចម្លងតែលេខកូដ។ កម្មវិធីអ្នកបង្កើតលេខកូដ កំណត់សុពលភាព និងផ្ទៀងផ្ទាត់ដោយខ្លួនឯង; វាលនេះគ្រប់គ្រងតែការបង្ហាញ និងចម្លង។ កម្មវិធីចាស់នៅអានសារបាន។

```json
{
  "chat_id": "USER_ID",
  "text": "លេខកូដចូលគំរូ៖ 003812 មានសុពលភាព 5 នាទី។",
  "copy_text": "003812"
}
```

## ក្តារប៊ូតុងឆ្លើយតប

នេះជាក្តារប៊ូតុងអត្ថបទច្រើនជួរ។ ចុចប៊ូតុងនឹងផ្ញើស្លាកជាសារធម្មតា; ដោះស្រាយតាម message.text ក្នុង getUpdates។

មាន 1–8 ជួរ 1–4 ប៊ូតុងក្នុងមួយជួរ សរុបមិនលើស 24។ ស្លាក 1–64 តួ មិនទទេ មិនមានបន្ទាត់ថ្មី ឬតួបញ្ជា។ ប៊ូតុងជាខ្សែអក្សរ ឬវត្ថុដែលមានតែ text។

បើមិនផ្ញើ reply_markup ក្តារចាស់នៅដដែល; ក្តារថ្មីជំនួសចាស់។ ផ្ញើ remove_keyboard: true តែឯងដើម្បីលុបក្តារ និងប៊ូតុងបើក។

អ្នកប្រើអាចបិទបង្រួម ឬបើក។ ក្តារប្រើម្ដងបិទក្រោយផ្ញើប៊ូតុងជោគជ័យ; កំណែថ្មីបើកវិញ។ ស្ថានភាពដាច់ដោយបូត/អ្នកប្រើ និងពិនិត្យប្រហែលរៀងរាល់ 5 វិនាទីពេលសន្ទនាសកម្ម។

ក្តារសម្រាប់ឯកជនតែប៉ុណ្ណោះ; ក្រុមមាន reply_markup ត្រឡប់ 422។ text នៅតែតម្រូវ។ ប្រើ JSON true/false មិនមែនខ្សែអក្សរ។ លក្ខណៈក្តារ/ប៊ូតុងមិនស្គាល់ត្រូវបដិសេធ។ reply_markup ជាខ្សែអក្សរ JSON អតិបរមា 16 KiB។

| ប៉ារ៉ាម៉ែត្រ | ប្រភេទ | តម្រូវ | ការពិពណ៌នា |
| --- | --- | --- | --- |
| `reply_markup` | object / JSON string | ទេ | វត្ថុក្តារប៊ូតុង ឬខ្សែអក្សរ JSON មិនបង្ខំ។ |
| `keyboard` | array[] | បាទ/ចាស | អារេពីរវិមាត្រ អារេរងមួយជាជួរមួយ។ |
| `resize_keyboard` | boolean | ទេ | លំនាំដើម true ប៊ូតុងតូច; false ប៊ូតុងខ្ពស់ជាង។ |
| `one_time_keyboard` | boolean | ទេ | លំនាំដើម false; true បិទក្រោយផ្ញើប៊ូតុងជោគជ័យ។ |
| `remove_keyboard` | boolean | ទេ | true លុបក្តារ មិនរួមជាមួយជម្រើសក្តារផ្សេង។ |

```json
{
  "chat_id": "USER_ID",
  "text": "ជ្រើសសេវាកម្ម៖",
  "reply_markup": {
    "keyboard": [
      [
        {
          "text": "កំណត់ភាសា"
        },
        {
          "text": "តាមដានបញ្ញើ"
        }
      ],
      [
        {
          "text": "ការជូនដំណឹង"
        },
        {
          "text": "បញ្ចូលលេខបញ្ញើ"
        }
      ]
    ],
    "resize_keyboard": true,
    "one_time_keyboard": false
  }
}
```

```json
{
  "chat_id": "USER_ID",
  "text": "ជ្រើសសេវាកម្ម៖",
  "reply_markup": {
    "keyboard": [
      [
        "កំណត់ភាសា",
        "តាមដានបញ្ញើ"
      ]
    ],
    "one_time_keyboard": true
  }
}
```

```json
{
  "chat_id": "USER_ID",
  "text": "ប្រតិបត្តិការបានបញ្ចប់។",
  "reply_markup": {
    "remove_keyboard": true
  }
}
```

## getUpdates · ទទួលសារ

`POST https://im.ez7.life/bot-api/<BOT_TOKEN>/getUpdates`

ជាការទាញរយៈពេលខ្លី: គ្មានសារនឹងត្រឡប់អារេទទេភ្លាម។ ហៅរៀងរាល់ 1–3 វិនាទី ហើយបង្កើនពេលរង់ចាំពេលមានកំហុស។ មិនមាន webhook សាធារណៈ ឬការទាញរយៈពេលវែង។

ក្រោយជោគជ័យ កំណត់ offset = update_id ចុងក្រោយ + 1; ព្រឹត្តិការណ៍មុនត្រូវបានបញ្ជាក់ទទួល។ បើបរាជ័យរក្សា offset ចាស់ និងការពារស្ទួនដោយ update_id ឬកូនសោអាជីវកម្ម។

សម្របសម្រួលកម្មវិធីទទួលសម្រាប់បូតតែមួយ កុំឱ្យរំកិល offset គ្នា។ មើល content_type និង raw_content សម្រាប់មាតិកាមិនមែនអត្ថបទ។

| ប៉ារ៉ាម៉ែត្រ | ប្រភេទ | តម្រូវ | ការពិពណ៌នា |
| --- | --- | --- | --- |
| `offset` | integer | ទេ | ID ព្រឹត្តិការណ៍បន្ទាប់មិនអវិជ្ជមាន លំនាំដើម 0។ |
| `limit` | integer | ទេ | 1–100 ព្រឹត្តិការណ៍ក្នុងមួយសំណើ លំនាំដើម 100។ |

```bash
curl --fail-with-body --request POST \
  "https://im.ez7.life/bot-api/${EZLIFE_BOT_TOKEN}/getUpdates" \
  --header 'Content-Type: application/json' \
  --data '{"offset": 0, "limit": 100}'
```

```json
{
  "ok": true,
  "result": [
    {
      "update_id": 120,
      "message": {
        "message_id": "EXAMPLE_MESSAGE_ID",
        "date": 1794297600,
        "chat": {
          "id": "1000000001",
          "type": "private"
        },
        "from": {
          "id": "1000000001",
          "display_name": "Example User"
        },
        "text": "កំណត់ភាសា",
        "content_type": 101,
        "raw_content": "{\n  \"content\": \"កំណត់ភាសា\"\n}"
      }
    }
  ]
}
```

| ប៉ារ៉ាម៉ែត្រ | ការពិពណ៌នា |
| --- | --- |
| `update_id` | ID កើនឡើងសម្រាប់បញ្ជាក់ទទួល។ |
| `message_id` | ID សារនៅលើវេទិកា។ |
| `date` | ពេលវេលា Unix គិតជាវិនាទី។ |
| `chat` | ID អ្នកផ្ញើឯកជន ឬ ID ក្រុម ជាមួយប្រភេទ private/group។ |
| `from` | ID និងឈ្មោះបង្ហាញរបស់អ្នកផ្ញើពិត។ |
| `text` | អត្ថបទ អាចទទេសម្រាប់ព្រឹត្តិការណ៍ផ្សេង។ |
| `content_type` | ប្រភេទមាតិកា; 101 គឺអត្ថបទ។ |
| `raw_content` | មាតិកាដើមនៃរូបភាព ឯកសារ និងព្រឹត្តិការណ៍ផ្សេង។ |

## កម្មវិធី Python ពេញលេញ

ឧទាហរណ៍ពេញប្រើបណ្ណាល័យស្តង់ដារ Python តែប៉ុណ្ណោះ ទទួល /start, /ping និងស្លាកប៊ូតុង ព្រមទាំងរក្សា offset។ ដំណើរការក្នុងថតឯកជន។

ជំនួសការដោះស្រាយប៊ូតុងគំរូដោយអាជីវកម្មពិត។ ការបញ្ជាទិញ ឬបង់ប្រាក់ត្រូវការពារធ្វើស្ទួន មុនរក្សាវឌ្ឍនភាព។

```python
import json
import os
import time
import urllib.error
import urllib.request
from pathlib import Path

TOKEN = os.environ["EZLIFE_BOT_TOKEN"]
BASE = "https://im.ez7.life/bot-api/" + TOKEN
OFFSET_FILE = Path("bot-offset.json")
MENU = [
  [
    "កំណត់ភាសា",
    "តាមដានបញ្ញើ"
  ],
  [
    "ការជូនដំណឹង",
    "បញ្ចូលលេខបញ្ញើ"
  ]
]

class ApiFailure(Exception):
    pass

class NoRedirect(urllib.request.HTTPRedirectHandler):
    def redirect_request(self, *args):
        return None

HTTP = urllib.request.build_opener(NoRedirect())

def api(method, payload):
    req = urllib.request.Request(
        BASE + "/" + method,
        data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    try:
        with HTTP.open(req, timeout=20) as response:
            body = json.load(response)
    except urllib.error.HTTPError as error:
        raise ApiFailure("HTTP " + str(error.code)) from None
    except (urllib.error.URLError, TimeoutError, OSError, ValueError):
        raise ApiFailure("Network or response failure") from None
    if not body.get("ok"):
        raise ApiFailure("API error " + str(body.get("error_code", "unknown")))
    return body["result"]

def handle(update):
    message = update.get("message", {})
    chat = message.get("chat", {})
    text = message.get("text", "")
    if not chat.get("id"):
        return
    payload = {"chat_id": str(chat["id"]),
               "chat_type": chat.get("type", "private")}
    if text == "/start" and payload["chat_type"] == "private":
        payload.update(text="ជ្រើសសេវាកម្ម៖", reply_markup={
            "keyboard": MENU, "resize_keyboard": True,
            "one_time_keyboard": False,
        })
    elif text == "/ping":
        payload["text"] = "pong"
    elif text in [label for row in MENU for label in row]:
        payload["text"] = "ប្រតិបត្តិការបានបញ្ចប់។"
    else:
        return
    api("sendMessage", payload)

def save_offset(value):
    temp = OFFSET_FILE.with_suffix(".tmp")
    fd = os.open(temp, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
    with os.fdopen(fd, "w", encoding="utf-8") as stream:
        json.dump(value, stream)
        stream.flush()
        os.fsync(stream.fileno())
    os.replace(temp, OFFSET_FILE)

def main():
    offset = json.loads(OFFSET_FILE.read_text()) if OFFSET_FILE.exists() else 0
    if isinstance(offset, bool) or not isinstance(offset, int) or offset < 0:
        raise ValueError("Invalid offset file")
    delay = 1
    while True:
        try:
            updates = api("getUpdates", {"offset": offset, "limit": 100})
            for update in updates:
                handle(update)
                next_offset = int(update["update_id"]) + 1
                save_offset(next_offset)
                offset = next_offset
            delay = 1
            time.sleep(2)
        except (ApiFailure, OSError, ValueError):
            print("Processing failed; offset retained. Check configuration.", flush=True)
            time.sleep(delay)
            delay = min(delay * 2, 30)

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        pass
```

## ក្រុម និងវិសាលភាពសារ

បូតត្រូវចូលក្រុមគោលដៅជាមុន។ តាមលំនាំដើមម្ចាស់ត្រូវអនុម័ត; ពិនិត្យនៅសន្ទនាបូត → បន្ថែម → ការកំណត់បូត → ក្រុមដែលបានចូល។

របៀបឯកជនក្រុមបិទតាមលំនាំដើម; ក្រុមបើកទទួលមិនចាំបាច់ @បូត។ សាររបស់បូតខ្លួនឯងមិនចូលជួរទទួលខ្លួន; សេចក្តីជូនដំណឹងវដ្ដក្រុមមិនមែនសារធម្មតា។

កុងតាក់ទទួលតាមក្រុមគ្រប់គ្រងព្រឹត្តិការណ៍ ការបញ្ជូនបន្ត និងឆ្លើយស្វ័យប្រវត្តិ។ បូតរបស់អ្នកប្រើបញ្ជូនសារក្រុមបើកទទួលទៅសារឯកជនម្ចាស់ដោយមានឈ្មោះក្រុម។ សិទ្ធិចូលពីក្រៅនៅគ្រប់គ្រង API និងការទទួល។

## ការកំណត់ និងឆ្លើយតបស្វ័យប្រវត្តិ

មានតែម្ចាស់អាចកំណត់អនុម័តចូលក្រុម ចូលពីក្រៅ ទទួលតាមក្រុម និងឆ្លើយតាមពាក្យគន្លឹះ។ បិទពីក្រៅរក្សា Token ប៉ុន្តែបដិសេធការហៅ API។

អតិបរមា 50 ច្បាប់; ពាក្យគន្លឹះ 1–100 តួ និងចម្លើយ 1–2000។ ផ្គូផ្គងការមានពាក្យដោយមិនបែងចែកអក្សរធំតូច តាមលំដាប់; ច្បាប់បើកដំបូងដែលត្រូវគ្នានឹងឆ្លើយ។

ឆ្លើយស្វ័យប្រវត្តិក្នុងឯកជន និងក្រុមបើកទទួល ដោយការពារបូតឆ្លើយតៗគ្នា។ AI API នៅជាផែនការ មិនមានវិធីសាធារណៈ។

## ដោះស្រាយកំហុស

កំហុសបញ្ចូលដំបូងដូចជា JSON ខុស ឬមាតិកាធំពេក ប្រើ errorCode និង message។ កំហុស API ផ្សេងប្រើ error_code និង description។ ពិនិត្យ HTTP និង ok ជាមុន។

```json
{
  "ok": false,
  "error_code": 422,
  "description": "chat_id 与 1–5000 字的 text 为必填"
}
```

| ស្ថានភាព | វិធីដោះស្រាយ |
| --- | --- |
| 400 | JSON មិនត្រឹមត្រូវ។ ពិនិត្យការអ៊ិនកូដ និងវាក្យសម្ពន្ធ។ |
| 401 | Token ខុស ដកហូត ចេញថ្មី ឬបូតផ្អាក។ ប្តូរព័ត៌មានសម្ងាត់។ |
| 403 | ម្ចាស់បិទការចូលពីក្រៅ។ បើកក្នុងការកំណត់បូត។ |
| 404 | ពិនិត្យផ្លូវ /bot-api/ ទម្រង់ Token និងឈ្មោះវិធីសាស្ត្រ។ |
| 409 | កំពុងធ្វើបច្ចុប្បន្នភាពក្តារបូត/អ្នកប្រើនេះ។ សាកម្តងទៀតបន្តិចទៀត។ |
| 413 | សំណើលើស 1 MiB។ បន្ថយទំហំ។ |
| 422 | កែប៉ារ៉ាម៉ែត្រ ទម្រង់លេខកូដ ឬរចនាសម្ព័ន្ធក្តារ។ |
| 500 | កំហុសបណ្ដោះអាសន្ន។ រក្សា offset និងបង្កើនពេលរង់ចាំ; ពិនិត្យលទ្ធផលផ្ញើមុនសាកវិញ។ |

## ដែនកំណត់ និងកម្មវិធីដែលគាំទ្រ

ឯកសារនេះតាម API បច្ចុប្បន្ន។ មិនទាន់មានវិធីផ្ញើមេឌៀ ប៊ូតុង inline callback ស្នើទំនាក់ទំនង/ទីតាំង ឬ webhook សាធារណៈ។

ក្តារត្រូវការ Web/H5 បច្ចុប្បន្ន។ កម្មវិធីបង្កប់ H5 ចាស់ត្រូវធ្វើបច្ចុប្បន្នភាពដើម្បីឃើញប៊ូតុងថ្មី។

សំណើពេញអតិបរមា 1 MiB។ កែប្រេកង់តាមបន្ទុកពិត; មគ្គុទ្ទេសក៍មិនធានាអត្រាថេរ។ សញ្ញាសមត្ថភាពក្រុមមិនជំនួសសមាជិកភាព ការអនុម័ត និងសិទ្ធិទទួល។

