Блокировка порно контента ботом

← К списку тем

Здравствуйте, посоветовали хороший сервис, который сканирует фото и определяет порно это или нет, там свободные АПИ и люди уже начали привязывать это к своим ботам, минус один у них в том, что нет примеров кода на РНР, есть на Питоне и других языках, может быть у вас получится на РНР это реализовать?

Это было бы очень полезно, бот бы мог допустим из чатов где он Админ удалять порно фотки с помощью такой функции!

https://www.clarifai.com/models/nsfw-image-recognition-model-e9576d86d2004ed1a38ba0cf39ecb4b1
Грачик Абдулошвили 10.02.2020 в 17:44

Авторизуйтесь через Telegram, чтобы ответить.
Откройте бот @SiteAuthBot, нажмите кнопку Старт/Start. Следуйте инструкциям бота.


Ответы

  • На PHP у них есть целая библиотека.
    composer require clarifai/clarifai-php
    Накидал простого бота т.к. времени разбираться в их библиотеке нет, хотя на сайте сервиса есть примеры для всех возможностей.

    После отправки картинки или видео в бот, идет проверка на порно-контент через сервис Сlarifai Predict API, в случае успешной проверки картинки
    Checked is successful: <br />
    sfw = 0.9961383<br />
    nsfw = 0.0038617323
    в случае успешной проверки видео
    Checked is successful: <br />
    Index#0:<br />
    sfw = 0.8625693<br />
    nsfw = 0.13743071<br />
    <br />
    Index#1:<br />
    sfw = 0.5390134<br />
    nsfw = 0.4609866<br />
    <br />
    Index#2:<br />
    sfw = 0.7888862<br />
    nsfw = 0.21111383<br />
    <br />
    ... кол-во блоков Index зависит от размера видео<br />
    <br />
    Index#n:<br />
    sfw = 0.51164865<br />
    nsfw = 0.4883513<br />
    <br />
    ---<br />
    Total result: <br />
    sfw = 0.8<br />
    nsfw = 0.2
    Вероятности для nsfw (порно-контент) и sfw (остальной контент), которые в сумме составляют 1,0. Как правило, если вероятность nsfw составляет менее 0,15, она, скорее всего, это не порно-контент. Если вероятность nsfw больше 0,85, скорее всего, порно-контент преобладает.

    Сервис анализирует каждую секунду видео, в примере кода бот выводит информацию о каждой проверенной секунде и после общий итог. Тестируйте на видео до 30 секунд или закомментируйте вывод информации по секундно, иначе текста получиться много и телеграм из-за ограничений кол-ва знаков в тексте не выведет вам результат вообще.

    Если проверка закончилась неудачно, то вернется код ошибки с описанием и деталями.
    Коды ошибок<br />
    https://docs.clarifai.com/getting-started/getting-started/status-codes
    iMakeBots 11.02.2020 в 12:20
  • Class CheckFileBot<br />
    {<br />
        private $data;<br />
        private $bot_token = ''; // токен бота<br />
        private $api_key = ''; // ключ https://portal.clarifai.com/apps после регистрации<br />
        private $api_url = 'https://api.clarifai.com/v2/models/e9576d86d2004ed1a38ba0cf39ecb4b1/outputs';<br />
        public function __construct()<br />
        {<br />
            $this->data = json_decode(file_get_contents('php://input'));<br />
            $this->route();<br />
        }<br />
        private function route()<br />
        {<br />
            if (isset($this->data->message)) {<br />
                if (isset($this->data->message->text)) {<br />
                    if ($this->data->message->text == "/start") {<br />
                        $this->hello();<br />
                    }<br />
                } elseif (<br />
                    isset($this->data->message->photo)<br />
                    || isset($this->data->message->video)<br />
                ) {<br />
                    $this->check();<br />
                }<br />
            }<br />
        }<br />
        private function hello()<br />
        {<br />
            $this->query("sendMessage", [<br />
                'chat_id' => $this->data->message->chat->id,<br />
                'text' => 'Hello, send me a picture'<br />
            ]);<br />
        }<br />
        private function getFileId()<br />
        {<br />
            if (isset($this->data->message->photo)) {<br />
                return end($this->data->message->photo)->file_id;<br />
            } elseif (isset($this->data->message->video)) {<br />
                return $this->data->message->video->file_id;<br />
            }<br />
            return null;<br />
        }<br />
        private function getType()<br />
        {<br />
            if (isset($this->data->message->photo)) {<br />
                return "image";<br />
            } elseif (isset($this->data->message->video)) {<br />
                return "video";<br />
            }<br />
            return null;<br />
        }<br />
        private function check()<br />
        {<br />
            $file_path = $this->query("getFile", [<br />
                'file_id' => $this->getFileId()<br />
            ])->result->file_path;<br />
            $result = $this->checkFile("https://api.telegram.org/file/bot" . $this->bot_token . "/" . $file_path);<br />
            if ($result->status->code == 10000) {<br />
                $text = "Checked is successful: \n";<br />
                if ($this->getType() == "image") {<br />
                    if (count($result->outputs[0]->data->concepts)) {<br />
                        foreach ($result->outputs[0]->data->concepts as $item) {<br />
                            $text .= $item->name . " = " . $item->value . "\n";<br />
                        }<br />
                    }<br />
                } elseif ($this->getType() == "video") {<br />
                    $result_data = [];<br />
                    $count_frames = count($result->outputs[0]->data->frames);<br />
                    if ($count_frames) {<br />
                        foreach($result->outputs[0]->data->frames as $frame) {<br />
                            $text .= "Index#" . $frame->frame_info->index .":\n";<br />
                            foreach ($frame->data->concepts as $item_) {<br />
                                $text .= $item_->name . " = " . $item_->value . "\n";<br />
                                $result_data[$item_->name] = isset($result_data[$item_->name])<br />
                                    ? $result_data[$item_->name] + $item_->value<br />
                                    : $item_->value;<br />
                            }<br />
                            $text .= "\n";<br />
                        }<br />
                        $text .= "---\nTotal result: \nsfw = " . round(($result_data['sfw'] / $count_frames), 2);<br />
                        $text .= "\nnsfw = " . round(($result_data['nsfw'] / $count_frames), 2);<br />
                    }<br />
                }<br />
            } else {<br />
                $text = "Checked is failed, try again\nCode is " . $result->status->code . " (" . $result->status->description . ": " . $result->status->details . ")";<br />
            }<br />
            $this->query("sendMessage", [<br />
                'chat_id' => $this->data->message->chat->id,<br />
                'text' => $text<br />
            ]);<br />
        }<br />
        private function query($method, $fields = [])<br />
        {<br />
            return json_decode(file_get_contents(<br />
                    'https://api.telegram.org/bot'<br />
                    . $this->bot_token . '/'<br />
                    . $method . '?'<br />
                    . http_build_query($fields))<br />
            );<br />
        }<br />
        private function checkFile($file)<br />
        {<br />
            $ch = curl_init($this->api_url);<br />
            curl_setopt_array($ch, array(<br />
                CURLOPT_POST => true,<br />
                CURLOPT_POSTFIELDS => json_encode([<br />
                    "inputs" => [<br />
                        [<br />
                            "data" => [<br />
                                $this->getType() => [<br />
                                    "url" => $file<br />
                                ]<br />
                            ]<br />
                        ]<br />
                    ]<br />
                ]),<br />
                CURLOPT_HTTPHEADER => [<br />
                    'Authorization: Key ' . $this->api_key,<br />
                    'Content-Type: application/json'<br />
                ],<br />
                CURLOPT_SSL_VERIFYPEER => 0,<br />
                CURLOPT_RETURNTRANSFER => 1,<br />
                CURLOPT_TIMEOUT => 10<br />
            ));<br />
            $r = json_decode(curl_exec($ch));<br />
            curl_close($ch);<br />
            return $r;<br />
        }<br />
    }<br />
    new CheckFileBot();
    iMakeBots 11.02.2020 в 12:21
    • все шикарно, ток я решил добавить еще удаление и рестрикт на того кто добавил порно контент. удаление то срабатывает,а когда добавил еще и Рестрикт то уже нет( посмотрите пожалуйста- https://prnt.sc/r2oyb1
      Грачик Абдулошвили 15.02.2020 в 16:38
      • Бот как используете? в приватной беседе или в группе?
        iMakeBots 15.02.2020 в 17:24
        • в чате конечно.
          это все тот же бот который за спам накладывал рестрикт (вы мне этот код присылали ранее в соседней ветке) теперь я его пытаюсь добавить еще и на порно контент чтобы не только удалялся этот контент но и рестрикт накладывался.
          Грачик Абдулошвили 15.02.2020 в 17:32
          • Ошибки в коде не вижу (не тестировал).
            Посмотрите, что возвращает Телеграм - при вызовах методов delete и restrict.
            iMakeBots 15.02.2020 в 17:47
            • ошибка очевидно в рестрикт, так как когда я удаляю код с рестриктом и оставляю ТОЛЬКО делит то все работает, когда добавляю строки Рестрикта то перестает даже удаляться..
              Грачик Абдулошвили 15.02.2020 в 17:53
            • Посмотрите какую ошибку возвращает метод
              iMakeBots 15.02.2020 в 17:54
            • для этого нужно лог файл создать чтобы туда все писалось?
              Грачик Абдулошвили 15.02.2020 в 18:01
            • file_put_contents('log.txt', $this);
              такой?? https://prnt.sc/r2qtkf
              Грачик Абдулошвили 15.02.2020 в 18:05
            • гуд!
              Грачик Абдулошвили 24.02.2020 в 14:49
          • private function setFileLog($data) {<br />
                    $fh = fopen('log.txt', 'a') or die('can't open file');<br />
                    ((is_array($data)) || (is_object($data))) ? fwrite($fh, print_r($data, TRUE).&quot;n&quot;) : fwrite($fh, $data . &quot;n&quot;);<br />
                    fclose($fh);<br />
                }
            iMakeBots 15.02.2020 в 18:03
            • вставил- https://prnt.sc/r2qwio

              бот уснул полностью.
              Грачик Абдулошвили 15.02.2020 в 18:14
            • есть какие нибудь идеи?)))
              Грачик Абдулошвили 16.02.2020 в 15:25
            • 1. Вызов метода не видно.
              2. Гадать тут сложно, вам надо отладкой выяснить где и какая ошибка выпадает.
              iMakeBots 16.02.2020 в 15:28
            • ВСЕ топичк, единственное что надо GIF добавить, так как их он не определяет(( хотя на сайте самом он может их читать, то есть видимо нужно третий тип файла добавить?
              Грачик Абдулошвили 24.02.2020 в 01:20
            • Надо поймать гиф и направить в сервис как видео.

              Сейчас скрипт ловит только видео и фото, остальное игнорит
              iMakeBots 24.02.2020 в 01:24
            • вот так надо сделать?
              private function getType()<br />
                  {<br />
                      if (isset($this-&gt;data-&gt;message-&gt;photo)) {<br />
                          return &quot;image&quot;;<br />
                      } elseif (isset($this-&gt;data-&gt;message-&gt;video)) {<br />
                          return &quot;video&quot;;<br />
                      }<br />
                  } elseif (isset($this-&gt;data-&gt;message-&gt;animation)) {<br />
                          return &quot;animation&quot;;<br />
                      }<br />
                      return null;<br />
                  }<br />
                  private function check()<br />
                  {<br />
                      $file_path = $this-&gt;query(&quot;getFile&quot;, [<br />
                          'file_id' =&gt; $this-&gt;getFileId()<br />
                      ])-&gt;result-&gt;file_path;<br />
                      $result = $this-&gt;checkFile(&quot;https://api.telegram.org/file/bot&quot; . $this-&gt;bot_token . &quot;/&quot; . $file_path);<br />
                      if ($result-&gt;status-&gt;code == 10000) {<br />
                          $text = &quot;Checked is successful: n&quot;;<br />
                          if ($this-&gt;getType() == &quot;image&quot;) {<br />
                              if (count($result-&gt;outputs[0]-&gt;data-&gt;concepts)) {<br />
                                  foreach ($result-&gt;outputs[0]-&gt;data-&gt;concepts as $item) {<br />
                                      $text .= $item-&gt;name . &quot; = &quot; . $item-&gt;value . &quot;n&quot;;<br />
                                  }<br />
                              }<br />
                          } elseif ($this-&gt;getType() == &quot;video&quot;) {<br />
                              $result_data = [];<br />
                              $count_frames = count($result-&gt;outputs[0]-&gt;data-&gt;frames);<br />
                              if ($count_frames) {<br />
                                  foreach($result-&gt;outputs[0]-&gt;data-&gt;frames as $frame) {<br />
                                      $text .= &quot;Index#&quot; . $frame-&gt;frame_info-&gt;index .&quot;:n&quot;;<br />
                                      foreach ($frame-&gt;data-&gt;concepts as $item_) {<br />
                                          $text .= $item_-&gt;name . &quot; = &quot; . $item_-&gt;value . &quot;n&quot;;<br />
                                          $result_data[$item_-&gt;name] = isset($result_data[$item_-&gt;name])<br />
                                              ? $result_data[$item_-&gt;name]   $item_-&gt;value<br />
                                              : $item_-&gt;value;<br />
                                      }<br />
                                      $text .= &quot;n&quot;;<br />
                                  }<br />
                                  $text .= &quot;---nTotal result: nsfw = &quot; . round(($result_data['sfw'] / $count_frames), 2);<br />
                                  $text .= &quot;nnsfw = &quot; . round(($result_data['nsfw'] / $count_frames), 2);<br />
                              }<br />
                          }<br />
                       } elseif ($this-&gt;getType() == &quot;animation&quot;) {<br />
                              $result_data = [];<br />
                              $count_frames = count($result-&gt;outputs[0]-&gt;data-&gt;frames);<br />
                              if ($count_frames) {<br />
                                  foreach($result-&gt;outputs[0]-&gt;data-&gt;frames as $frame) {<br />
                                      $text .= &quot;Index#&quot; . $frame-&gt;frame_info-&gt;index .&quot;:n&quot;;<br />
                                      foreach ($frame-&gt;data-&gt;concepts as $item_) {<br />
                                          $text .= $item_-&gt;name . &quot; = &quot; . $item_-&gt;value . &quot;n&quot;;<br />
                                          $result_data[$item_-&gt;name] = isset($result_data[$item_-&gt;name])<br />
                                              ? $result_data[$item_-&gt;name]   $item_-&gt;value<br />
                                              : $item_-&gt;value;<br />
                                      }<br />
                                      $text .= &quot;n&quot;;<br />
                                  }<br />
                                  $text .= &quot;---nTotal result: nsfw = &quot; . round(($result_data['sfw'] / $count_frames), 2);<br />
                                  $text .= &quot;nnsfw = &quot; . round(($result_data['nsfw'] / $count_frames), 2);<br />
                              }<br />
                          }<br />
                      } else {<br />
                          $text = &quot;Checked is failed, try againnCode is &quot; . $result-&gt;status-&gt;code . &quot; (&quot; . $result-&gt;status-&gt;description . &quot;: &quot; . $result-&gt;status-&gt;details . &quot;)&quot;;<br />
                      }<br />
                      $this-&gt;query(&quot;sendMessage&quot;, [<br />
                          'chat_id' =&gt; $this-&gt;data-&gt;message-&gt;chat-&gt;id,<br />
                          'text' =&gt; $text<br />
                      ]);<br />
                  }
              Грачик Абдулошвили 24.02.2020 в 01:53
            • или можно вот так упростить и анимацию в видео отправлять просто?
                 private function getType()<br />
                  {<br />
                      if (isset($this-&gt;data-&gt;message-&gt;photo)) {<br />
                          return &quot;image&quot;;<br />
                      } elseif (isset($this-&gt;data-&gt;message-&gt;video)) {<br />
                          return &quot;video&quot;;<br />
                      }<br />
                } elseif (isset($this-&gt;data-&gt;message-&gt;animation)) {<br />
                          return &quot;video&quot;;<br />
                      }<br />
                      return null;<br />
                  }
              Грачик Абдулошвили 24.02.2020 в 01:57
            • Да, можно:
               elseif (isset($this-&gt;data-&gt;message-&gt;video) || isset($this-&gt;data-&gt;message-&gt;animation))

              Всего надо внести изменения методах: route, getFileId, getType
              iMakeBots 24.02.2020 в 11:47
            • прописал вот так- https://prnt.sc/r6v7cn
              в итоге фото и видео работают как и раньше а на ГИФКИ проверка выдает- Checked is failed, try again
              Code is 10020 (Failure: )
              Грачик Абдулошвили 24.02.2020 в 14:49
            • В методе getFileId вы берете file_id из объекта video, которого у обновления при animation просто нет, поэтому вы и получаете ошибку 10020 - вы не присылаете файл для обработки.
              iMakeBots 24.02.2020 в 16:30
            • Вот для ГИФок надо прописывать и тогда все ОК
              https://prnt.sc/r6z65j
              Грачик Абдулошвили 24.02.2020 в 19:03
            • Да, все верно - надо передавать animation file_id
              iMakeBots 24.02.2020 в 20:59
    • Спамеры пошли дальше((((
      теперь они шлют порнуху не в виде картинки а в виде ссылки на фото и это фото соответсвенно не подвергается проверки а раскрывается в чате как предпросмотр(((
      Можно ли как то прописать в код отправлять на порно-проверку еще и все ссылки от пользователей?
      Грачик Абдулошвили 24.02.2020 в 23:56
      • Можно. В обновлении, которое прилетает от вебхук есть объект entities в нем лежат данные по сущностям в том числе и ссылкам.
        Можно по координатам (они там же в объекте) из сообщения доставать ссылку и направлять на проверку в сервис.
        iMakeBots 25.02.2020 в 06:54