GithubHelp home page GithubHelp logo

Comments (9)

rudykojot avatar rudykojot commented on July 19, 2024 1

@seratch Sorry for the hold up. Yesss that helped Thank You very much. Maybe not directly but with that we were able to rewrite some logic. So if someone need's working code here it is:

import datetime
import sys
import time
import slack_sdk
from slack_sdk.errors import SlackApiError
from slack_sdk import WebClient

sys.path.append(r'C:\Users\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
SLACK_API_TOKEN = 'xoxb-1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1'

ARCHIVE_LAST_MESSAGE_AGE_DAYS = 360

oldest_message_time_to_prevent_archive = (
    datetime.datetime.now() - datetime.timedelta(days=ARCHIVE_LAST_MESSAGE_AGE_DAYS)
).timestamp()

client = WebClient(SLACK_API_TOKEN)

my_user_id = client.auth_test()['user_id']

processed_channels = set()


def post_archive_message(channel_name):
    message = (
        f"The Slack channel '{channel_name}' has been archived due to long inactivity.\n\n"
        "If you have any questions, doubts, or if you wish to unarchive the channel, "
        "please feel free to raise an IT ticket at [IT Ticket System](https:/xxxxxxxxxxxxxxcom/)."
    )
    response = client.chat_postMessage(channel=f"#{channel_name}", text=message)
    print(response)


def channel_has_recent_messages(channel_id):
    # Getting up to 2 messages younger than ARCHIVE_LAST_MESSAGE_AGE_DAYS
    global response

    if channel_id in processed_channels:
        return False
    real_messages = []
    try:
        response = client.conversations_history(
            channel=channel_id,
            oldest=str(oldest_message_time_to_prevent_archive),
            limit=5
        )
        # Filter out message about our bot joining this channel
        if response["messages"] is not None:
            for m in response["messages"]:
                if 'user' not in m or m['user'] != my_user_id:
                    real_messages.append(m)
            if real_messages:
                print('#' + channel['name'] + ': Has recent messages')
            time.sleep(2)
        else:
            print("No conversation history")
    except slack_sdk.errors.SlackApiError as e:
        print(e)

    # If we found at least one - return True, if not - False
    return any(message for message in real_messages)


max_retries = 1
retry_delay = 61
next_cursor = None

response = client.conversations_list(
    exclude_archived=True,
    limit=999,
    types=["public_channel", "private_channel"]
)

for page in response:
    print('Going to next page....')
    for channel in page['channels']:
        if not channel['is_member']:
            for retry_count in range(max_retries):
                try:
                    client.conversations_join(channel=channel['id'])
                except slack_sdk.errors.SlackApiError as e:
                    print(f"Slack API error while joining channel {channel['name']}: {e.response['error']}")
                    if retry_count < max_retries - 1:
                        print(f"Retrying in {retry_delay} seconds...")
                        time.sleep(retry_delay)
                    else:
                        print("Max retries reached. Skipping this channel.")
                        continue
        if channel_has_recent_messages(channel['id']):
            print('#' + channel['name'] + ': looks active')
        else:
            print('There is no messages or threads found in #' + channel['name'])
            print('#' + channel['name'] + ': archiving')

            try:
                for retry_count in range(max_retries):
                    try:
                        client.conversations_archive(channel=channel['id'])
                        post_archive_message(channel['name'])  # Post the archive message
                        break
                    except slack_sdk.errors.SlackApiError as e:
                        print(f"Slack API error while archiving channel {channel['name']}: {e.response['error']}")
                        if retry_count < max_retries - 1:
                            print(f"Retrying in {retry_delay} seconds...")
                            time.sleep(retry_delay)
                        else:
                            print("Max retries reached. Skipping this channel.")
                            break  # Skip to the next channel
            except Exception:
                print("There is no slack message")

Unfortunately during making this bot and trying everything i added so much Token scopes that i have no idea which really are needed and now im afraid to take them out, but In term of code itself this is the best way to go

from python-slack-sdk.

hello-ashleyintech avatar hello-ashleyintech commented on July 19, 2024

Hi, @rudykojot! Thank you for your question!

After taking a brief glance at your code and the error you received, I'm wondering what would happen if you tried to decrease the limit in the conversations_list API call. As noted in the docs:

This method uses cursor-based pagination to make it easier to incrementally collect information. To begin pagination, specify a limit value under 1000. We recommend no more than 200 results at a time.

I recommend trying to reduce the limit and seeing if that affects the results at all!

from python-slack-sdk.

rudykojot avatar rudykojot commented on July 19, 2024

@hello-ashleyintech Hey thanks for suggestion but this makes only to code crash sooner

from python-slack-sdk.

seratch avatar seratch commented on July 19, 2024

The internal_error is totally Slack's server-side fault. If the error is temporarily occurring, adding ServerErrorRetryHandler to your WebClient instance may mitigate the issue. To learn how to enable it, please refer to the following resources:

from python-slack-sdk.

rudykojot avatar rudykojot commented on July 19, 2024

@seratch Unfortunetly this also did not help. On one side i know that this error suggest that this is slack server fault however, before it also gave me this error and the problem was with wrong indentation in the code so it's tricky

from python-slack-sdk.

seratch avatar seratch commented on July 19, 2024

I remember that the server can return "internal_error" when it fails to handle an unexpected argument data while such a request should be responded as client error. So, you may be able to find a workaround by modifying some parts of your code. That being said, I cannot pinpoint the cause of your situation with currently given information.

I know this could be frustrating but please contact our customer support team with your app and workspace information. They can check the server-side logs and communicate with engineering teams for you.

from python-slack-sdk.

rudykojot avatar rudykojot commented on July 19, 2024

@seratch @hello-ashleyintech Little update after contacting slack support they responded me with those:

"I had a look in the logs for the past 7 days and the majority of the errors are related to conversations.replies being ratelimited. If you do reach the rate limit, then as mentioned in our Rate limit doc, you can rely on the Retry-After header to determine when you'll be able to send messages again:

https://api.slack.com/docs/rate-limits#headers
While rate limits cannot be increased, turned off, overridden, or otherwise changed, I would recommend implementing some kind of queueing system that handles the calls to keep below the rate limit.

Looking at conversations.list I see all the error=internal_error are related to status_true_error.keyword: Invalid encoded id Can you check that you are passing in correct data."

and another one after i tried implement some ratelimit logic and ask them if something changed:

"Not seeing any issues in relation to conversations.replies. I'm just seeing a few errors each day for conversations.list

error=internal_error Invalid encoded id

Are you validating your requests? Seems to be something invalid in your payload

https://api.slack.com/authentication/verifying-requests-from-slack#making__validating-a-request "

Anybody has some ideas how to fix it in my code?

from python-slack-sdk.

rudykojot avatar rudykojot commented on July 19, 2024

@seratch @hello-ashleyintech (another update) I will copy my message for slack support to save time maybe you have some idea on if we are right or maybe have some ideas to fix it, because i think me and my collogue found where the issue lies.

"Ok so after reviewing the code carefully with some support and investigating on when the code crushes i think the most possible reason it's that the "next_cursor" method in conversations.list doesn't work properly, This is most possible because if we change the limit for 10 it crashes after 10, if we change it to 999 it crashes after 999, so there is no problem with specific channels there is a problem with reaching next pagination and since the max limit is 999 and we have over 4000 channels it will never gonna clean all of them, So my question is is it possible that my code or bot settings are lacking something to reach next pagination or is it problem or slack_sdk client side and now we have to wait until it get fixed. It might be helpful to add that we are able to "extract" next cursor value so most likely code logic is correct."

from python-slack-sdk.

seratch avatar seratch commented on July 19, 2024

I am not sure if this could be helpful for you, but this SDK provides an easy to paginate this way: https://github.com/slackapi/python-slack-sdk/blob/v3.23.0/tests/slack_sdk/web/test_web_client.py#L47-L52 Relying on the built-in feature instead of trying to do pagnation on your own may help.

from python-slack-sdk.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.