Skip to content

Commit

Permalink
Support starting wee-slack without using rtm.start
Browse files Browse the repository at this point in the history
rtm.start is deprecated and will stop working on September 20, 2022.
This patch replaces it with several other API endpoints to get the info
we need.

The old code to use rtm.start is still kept because xoxs tokens doesn't
work with the users.conversations API endpoint, but it will probably be
removed soon (it's not possible to get new xoxs tokens anyways).

This is a necessary step for #699 and #844
  • Loading branch information
trygveaa committed Jan 30, 2022
1 parent c448123 commit cf55d0d
Showing 1 changed file with 203 additions and 6 deletions.
209 changes: 203 additions & 6 deletions wee_slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,9 @@ def handle_next(self):
metadata["user"] = team.users.get(user_id)

dbg("running {}".format(function_name))
if (
if callable(metadata.get("callback")):
metadata["callback"](j, self, team, channel, metadata)
elif (
function_name.startswith("local_")
and function_name in self.local_proc
):
Expand Down Expand Up @@ -1426,6 +1428,7 @@ def __init__(
metadata=None,
retries=3,
token=None,
callback=None,
):
if team is None and token is None:
raise ValueError("Both team and token can't be None")
Expand All @@ -1436,10 +1439,14 @@ def __init__(
self.metadata = metadata if metadata else {}
self.retries = retries
self.token = token if token else team.token
self.callback = callback
self.domain = "api.slack.com"
self.reset()

def reset(self):
self.tries = 0
self.start_time = time.time()
self.request_normalized = re.sub(r"\W+", "", request)
self.domain = "api.slack.com"
self.request_normalized = re.sub(r"\W+", "", self.request)
self.post_data["token"] = self.token
self.url = "https://{}/api/{}?{}".format(
self.domain, self.request, urlencode(encode_to_utf8(self.post_data))
Expand Down Expand Up @@ -3234,7 +3241,7 @@ class SlackBot(SlackUser):
"""

def __init__(self, originating_team_id, **kwargs):
super(SlackBot, self).__init__(originating_team_id, is_bot=True, **kwargs)
super(SlackBot, self).__init__(originating_team_id, **kwargs)


class SlackMessage(object):
Expand Down Expand Up @@ -6688,6 +6695,193 @@ def initiate_connection(token, retries=3, team=None, reconnect=False):
)


def get_next_page(response_json):
next_cursor = response_json.get("response_metadata", {}).get("next_cursor")
if next_cursor:
request = response_json["wee_slack_request_metadata"]
request.post_data["cursor"] = next_cursor
request.reset()
EVENTROUTER.receive(request)
return True
else:
return False


def initiate_new(token):
initial_data = {
"channels": [],
"members": [],
"usergroups": [],
"complete": {
"channels": False,
"members": False,
"usergroups": False,
"prefs": False,
"presence": False,
},
}

def handle_initial(data_type):
def handle(response_json, eventrouter, team, channel, metadata):
if not response_json["ok"]:
print(response_json["error"])
return

initial_data[data_type].extend(response_json[data_type])

if not get_next_page(response_json):
initial_data["complete"][data_type] = True
create_team(token, initial_data)

return handle

def handle_prefs(response_json, eventrouter, team, channel, metadata):
if not response_json["ok"]:
print(response_json["error"])
return

initial_data["prefs"] = response_json["prefs"]
initial_data["complete"]["prefs"] = True
create_team(token, initial_data)

def handle_getPresence(response_json, eventrouter, team, channel, metadata):
if not response_json["ok"]:
print(response_json["error"])
return

initial_data["presence"] = response_json
initial_data["complete"]["presence"] = True
create_team(token, initial_data)

s = SlackRequest(
None,
"users.conversations",
{"types": "public_channel,private_channel,mpim,im", "limit": 1000},
token=token,
metadata={"callback": handle_initial("channels")},
)
EVENTROUTER.receive(s)
s = SlackRequest(
None,
"users.list",
{"limit": 1000},
token=token,
metadata={"callback": handle_initial("members")},
)
EVENTROUTER.receive(s)
s = SlackRequest(
None,
"usergroups.list",
{"include_users": True},
token=token,
metadata={"callback": handle_initial("usergroups")},
)
EVENTROUTER.receive(s)
s = SlackRequest(
None,
"users.prefs.get",
token=token,
metadata={"callback": handle_prefs},
)
EVENTROUTER.receive(s)
s = SlackRequest(
None,
"users.getPresence",
token=token,
metadata={"callback": handle_getPresence},
)
EVENTROUTER.receive(s)


def create_team(token, initial_data):
if all(initial_data["complete"].values()):

def handle_rtmconnect(response_json, eventrouter, team, channel, metadata):
if not response_json["ok"]:
print(response_json["error"])
return

team_id = response_json["team"]["id"]
myidentifier = response_json["self"]["id"]

users = {}
bots = {}
for member in initial_data["members"]:
if member.get("is_bot"):
bots[member["id"]] = SlackBot(team_id, **member)
else:
users[member["id"]] = SlackUser(team_id, **member)

self_nick = nick_from_profile(
users[myidentifier].profile, response_json["self"]["name"]
)

channels = {}
for channel in initial_data["channels"]:
channel["is_member"] = True
if channel.get("is_im"):
channel_instance = SlackDMChannel(eventrouter, users, **channel)
elif channel.get("is_shared"):
channel_instance = SlackSharedChannel(eventrouter, **channel)
elif channel.get("is_mpim"):
channel_instance = SlackMPDMChannel(
eventrouter, users, myidentifier, **channel
)
elif channel.get("is_private"):
channel_instance = SlackPrivateChannel(eventrouter, **channel)
else:
channel_instance = SlackChannel(eventrouter, **channel)
channels[channel["id"]] = channel_instance

subteams = {}
for usergroup in initial_data["usergroups"]:
is_member = myidentifier in usergroup["users"]
subteams[usergroup["id"]] = SlackSubteam(
team_id, is_member=is_member, **usergroup
)

manual_presence = (
"away" if initial_data["presence"]["manual_away"] else "active"
)

team_info = {
"id": team_id,
"name": response_json["team"]["id"],
"domain": response_json["team"]["domain"],
}

team_hash = SlackTeam.generate_team_hash(
team_id, response_json["team"]["domain"]
)
t = SlackTeam(
eventrouter,
token,
team_hash,
response_json["url"],
team_info,
subteams,
self_nick,
myidentifier,
manual_presence,
users,
bots,
channels,
muted_channels=initial_data["prefs"]["muted_channels"],
highlight_words=initial_data["prefs"]["highlight_words"],
)
eventrouter.register_team(t)
t.connect()

s = SlackRequest(
None,
"rtm.connect",
{"batch_presence_aware": 1},
token=token,
metadata={"callback": handle_rtmconnect},
)
EVENTROUTER.receive(s)


if __name__ == "__main__":

w = WeechatWrapper(weechat)
Expand Down Expand Up @@ -6763,6 +6957,9 @@ def initiate_connection(token, retries=3, team=None, reconnect=False):
),
)
for t in tokens:
s = initiate_connection(t)
EVENTROUTER.receive(s)
if t.startswith("xoxs"):
s = initiate_connection(t)
EVENTROUTER.receive(s)
else:
initiate_new(t)
EVENTROUTER.handle_next()

0 comments on commit cf55d0d

Please sign in to comment.