← Вернуться к списку тем

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

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

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

https://www.clarifai.com/models/nsfw-image-recognition-model-e9576d86d2004ed1a38ba0cf39ecb4b1

Ответы


  • iMakeBots [11.02.2020 в 12:20 → Грачик Абдулошвили]
    На PHP у них есть целая библиотека.
    composer require clarifai/clarifai-php
    Накидал простого бота т.к. времени разбираться в их библиотеке нет, хотя на сайте сервиса есть примеры для всех возможностей.

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

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

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

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

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

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