Как можно отправить фотографию в группу и в чат ВКонтакте?

У меня есть бот, который пересылает сообщения из Discord в группу и чат ВК. Я создал приложение и получил его токен по следующей ссылке: <br/> <pre><code>https://oauth.vk.com/authorize?client_id=ТУТ АЙДИ&amp;display=page&amp;redirect_uri=https://oauth.vk.com/blank.html&amp;scope=notify,friends,audio,video,stories,status,notes,menu,pages,wall,photos,ads,offline,messages,docs,phone_number,notifications,email,stats,groups&amp;response_type=token&amp;v=5.131</code></pre> <br/> <br/> Я предоставил все необходимые scopes, чтобы избежать ошибок, однако при загрузке и отправке изображения возникает следующая ошибка: <br/> <pre><code>[15] Access denied: no access to call this method. It cannot be called with current scopes.</code></pre> <br/> <br/> Вот мой код: <br/> <pre><code class="python">async def post_to_vk(self, message: discord.Message):
        """Публикация сообщения в группу ВК и чат"""
        try:
            attachments = []

            # Обработка изображений
            if message.attachments:
                for attachment in message.attachments:
                    if any(attachment.filename.lower().endswith(ext) for ext in ['.jpg', '.jpeg', '.png']):
                        try:
                            # Скачиваем файл
                            await attachment.save(attachment.filename)

                            # Загружаем фото на сервер ВК
                            photo = self.upload.photo_wall(
                                attachment.filename,
                                user_id=self.vk.users.get()[0]['id']  # Получаем ID пользователя
                            )[0]

                            # Формируем строку для прикрепления
                            attachments.append(f"photo{photo['ow
  • 27 декабря 2024 г. 15:34
Ответы на вопрос 2
Чтобы успешно отправить фотографию в группу или чат ВКонтакте с использованием бота, вам нужно убедиться в нескольких ключевых моментах:

1. **Правильные права доступа**: Убедитесь, что у вашего токена есть разрешения на `photos` и `wall`. В вашем случае, в запросе на получение токена надо добавить `groups` и `photos`. Важно, чтобы ваш токен был получен именно от группы, а не от обычного пользователя.

2. **Используйте метод `photos.getWallUploadServer`**: Прежде чем загружать фотографии, нужно получить URL для загрузки. Используйте следующий метод:

    ```python
    upload_server = self.vk.photos.getWallUploadServer(group_id='YOUR_GROUP_ID')
    ```

3. **Загрузите фотографию на полученный URL**: Используйте библиотеку для HTTP-запросов, например `aiohttp`, чтобы загрузить файл на сервис ВК. При загрузке вам нужно будет также учесть формат данных. Пример кода для загрузки:

    ```python
    import aiohttp

    async with aiohttp.ClientSession() as session:
        with open('attachment.filename', 'rb') as file:
            data = aiohttp.FormData()
            data.add_field('photo', file)

            async with session.post(upload_server['upload_url'], data=data) as response:
                result = await response.json()
    ```

4. **Сохраните загруженную фотографию**: После успешной загрузки получите информацию о загруженной фотографии и сохраните её с помощью метода `photos.saveWallPhoto`:

    ```python
    saved_photo = self.vk.photos.saveWallPhoto(
        owner_id=result['owner_id'],
        photo=result['photo'],
        server=result['server'],
        hash=result['hash']
    )
    ```

5. **Формируйте вложения**: Используйте полученные данные для формирования вложения, как в вашем коде:

    ```python
    attachments.append(f"photo{saved_photo[0]['owner_id']}_{saved_photo[0]['id']}")
    ```

6. **Отправьте сообщение с вложением**: Когда вложения готовы, отправьте сообщение:

    ```python
    self.vk.messages.send(
        user_id=ваш_id_пользователя_или_группы,
        random_id=0,
        message='Текст вашего сообщения',
        attachment=','.join(attachments)
    )
    ```

Вот пример полного кода с учетом всех вышеуказанных шагов:

```python
async def post_to_vk(self, message: discord.Message):
    """Публикация сообщения в группу ВК и чат"""
    try:
        attachments = []

        # Обработка изображений
        if message.attachments:
            for attachment in message.attachments:
                if any(attachment.filename.lower().endswith(ext) for ext in ['.jpg', '.jpeg', '.png']):
                    # Скачиваем файл
                    await attachment.save(attachment.filename)

                    # Получение URL для загрузки
                    upload_server = self.vk.photos.getWallUploadServer(group_id='YOUR_GROUP_ID')

                    # Загрузка фото
                    async with aiohttp.ClientSession() as session:
                        with open(attachment.filename, 'rb') as file:
                            data = aiohttp.FormData()
                            data.add_field('photo', file)

                            async with session.post(upload_server['upload_url'], data=data) as response:
                                result = await response.json()

                    # Сохранение фотографии
                    saved_photo = self.vk.photos.saveWallPhoto(
                        group_id='YOUR_GROUP_ID',
                        **result
                    )

                    attachments.append(f"photo{saved_photo[0]['owner_id']}_{saved_photo[0]['id']}")

        # Отправка сообщения
        self.vk.messages.send(
            user_id='USER_OR_GROUP_ID',
            random_id=0,
            message='Текст вашего сообщения',
            attachment=','.join(attachments)
        )
    except Exception as e:
        print(f"Произошла ошибка при отправке сообщения: {e}")
```

Не забудьте заменить `YOUR_GROUP_ID` и `USER_OR_GROUP_ID` на актуальные значения. Также, проверьте, что ваш токен не имеет ограничения по правам доступа.
Ошибка `[15] Access denied: no access to call this method. It cannot be called with current scopes` указывает на то, что у вашего приложения VK API недостаточно прав для выполнения запрашиваемого действия. В частности, это может быть связано с тем, что токен, который вы используете, не имеет необходимых разрешений (scopes) для вызова методов `wall.post` или `messages.send`. 

### Решение проблемы:

1. **Проверьте токен доступа:**
Убедитесь, что токен, который вы используете, имеет необходимые разрешения. Для методов `wall.post` и `messages.send` требуются следующие scopes:
- `wall` — для публикации на стене.
- `messages` — для отправки сообщений в чат.

При получении токена через OAuth убедитесь, что вы запрашиваете эти разрешения. Например, при авторизации через ссылку:
```
https://oauth.vk.com/authorize?client_id=YOUR_CLIENT_ID&display=page&redirect_uri=YOUR_REDIRECT_URI&scope=wall,messages&response_type=code&v=5.131

```

2. **Обновите токен:**
Если текущий токен не имеет необходимых прав, получите новый токен с нужными scopes.

3. **Проверьте права группы:**
Убедитесь, что токен имеет доступ к группе, указанной в `VK_GROUP_ID`. Токен должен быть выдан для администратора группы или иметь права на публикацию на стене.

4. **Проверьте права чата:**
Убедитесь, что токен имеет доступ к чату, указанному в `VK_CHAT_ID`. Токен должен быть выдан для пользователя, который является участником чата.

### Пример исправленного кода:

```python
async def post_to_vk(self, message: discord.Message):
    """Публикация сообщения в группу ВК и чат"""
    try:
        attachments = []

        # Обработка изображений
        if message.attachments:
            for attachment in message.attachments:
                if any(attachment.filename.lower().endswith(ext) for ext in ['.jpg', '.jpeg', '.png']):
                    try:
                        # Скачиваем файл
                        await attachment.save(attachment.filename)

                        # Загружаем фото на сервер ВК
                        photo = self.upload.photo_wall(
                            attachment.filename,
                            user_id=self.vk.users.get()[0]['id']  # Получаем ID пользователя
                        )[0]

                        # Формируем строку для прикрепления
                        attachments.append(f"photo{photo['owner_id']}_{photo['id']}")

                    except Exception as photo_error:
                        print(f"Ошибка при загрузке фото: {photo_error}")
                        traceback.print_exc()
                    finally:
                        # Удаляем временный файл
                        if os.path.exists(attachment.filename):
                            os.remove(attachment.filename)

        # Публикуем в группу
        try:
            self.vk.wall.post(
                owner_id=-VK_GROUP_ID,  # Минус для групп
                message=message.content,
                attachments=','.join(attachments) if attachments else None
            )
        except Exception as wall_error:
            print(f"Ошибка при публикации на стену: {wall_error}")

        # Отправляем в чат
        try:
            self.vk.messages.send(
                chat_id=VK_CHAT_ID,
                message=message.content,
                attachment=','.join(attachments) if attachments else None,
                random_id=0
            )
        except Exception as message_error:
            print(f"Ошибка при отправке в чат: {message_error}")

    except Exception as e:
        print(f"Общая ошибка при публикации в ВК: {e}")
        traceback.print_exc()
```


### Дополнительные рекомендации:
- Убедитесь, что токен не истёк. Токены VK API имеют ограниченный срок действия, и их нужно обновлять.
- Если вы используете токен группы, убедитесь, что он имеет права на публикацию на стене и отправку сообщений.

Если после выполнения этих шагов ошибка сохраняется, проверьте документацию VK API и убедитесь, что вы используете правильные методы и параметры.
Похожие вопросы