arcade-slack 1.2.1__py3-none-any.whl → 2.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- arcade_slack/critics.py +1 -1
- arcade_slack/message_retrieval.py +2 -2
- arcade_slack/tools/chat.py +63 -612
- arcade_slack/tools/users.py +0 -15
- arcade_slack/user_retrieval.py +3 -3
- arcade_slack/utils.py +114 -2
- {arcade_slack-1.2.1.dist-info → arcade_slack-2.1.0.dist-info}/METADATA +1 -1
- {arcade_slack-1.2.1.dist-info → arcade_slack-2.1.0.dist-info}/RECORD +10 -10
- {arcade_slack-1.2.1.dist-info → arcade_slack-2.1.0.dist-info}/WHEEL +1 -1
- {arcade_slack-1.2.1.dist-info → arcade_slack-2.1.0.dist-info}/licenses/LICENSE +0 -0
arcade_slack/critics.py
CHANGED
|
@@ -4,7 +4,7 @@ from arcade_evals import BinaryCritic
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class RelativeTimeBinaryCritic(BinaryCritic):
|
|
7
|
-
def evaluate(self, expected: Any, actual: Any) -> dict[str,
|
|
7
|
+
def evaluate(self, expected: Any, actual: Any) -> dict[str, Any]:
|
|
8
8
|
"""
|
|
9
9
|
Evaluates whether the expected and actual relative time strings are equivalent after
|
|
10
10
|
casting.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from datetime import datetime, timezone
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
|
-
from arcade_tdk.errors import
|
|
4
|
+
from arcade_tdk.errors import FatalToolError
|
|
5
5
|
from slack_sdk.web.async_client import AsyncWebClient
|
|
6
6
|
|
|
7
7
|
from arcade_slack.utils import (
|
|
@@ -30,7 +30,7 @@ async def retrieve_messages_in_conversation(
|
|
|
30
30
|
error_message = "Cannot specify both 'latest_datetime' and 'latest_relative'."
|
|
31
31
|
|
|
32
32
|
if error_message:
|
|
33
|
-
raise
|
|
33
|
+
raise FatalToolError(error_message, developer_message=error_message)
|
|
34
34
|
|
|
35
35
|
current_unix_timestamp = int(datetime.now(timezone.utc).timestamp())
|
|
36
36
|
|
arcade_slack/tools/chat.py
CHANGED
|
@@ -21,6 +21,7 @@ from arcade_slack.user_retrieval import (
|
|
|
21
21
|
from arcade_slack.utils import (
|
|
22
22
|
async_paginate,
|
|
23
23
|
extract_conversation_metadata,
|
|
24
|
+
invite_users_to_conversation,
|
|
24
25
|
populate_users_in_messages,
|
|
25
26
|
raise_for_users_not_found,
|
|
26
27
|
)
|
|
@@ -420,646 +421,96 @@ async def list_conversations(
|
|
|
420
421
|
}
|
|
421
422
|
|
|
422
423
|
|
|
423
|
-
##################################################################################
|
|
424
|
-
# NOTE: The tools below are kept here for backwards compatibility. Prefer using: #
|
|
425
|
-
# - send_message
|
|
426
|
-
# - get_messages
|
|
427
|
-
# - get_conversation_metadata
|
|
428
|
-
# - get_users_in_conversation
|
|
429
|
-
# - list_conversations
|
|
430
|
-
##################################################################################
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
@tool(
|
|
434
|
-
requires_auth=Slack(
|
|
435
|
-
scopes=[
|
|
436
|
-
"channels:read",
|
|
437
|
-
"groups:read",
|
|
438
|
-
"mpim:read",
|
|
439
|
-
"im:read",
|
|
440
|
-
"users:read",
|
|
441
|
-
"users:read.email",
|
|
442
|
-
"chat:write",
|
|
443
|
-
# "mpim:write",
|
|
444
|
-
"im:write",
|
|
445
|
-
],
|
|
446
|
-
)
|
|
447
|
-
)
|
|
448
|
-
async def send_dm_to_user(
|
|
449
|
-
context: ToolContext,
|
|
450
|
-
user_name: Annotated[
|
|
451
|
-
str,
|
|
452
|
-
(
|
|
453
|
-
"The Slack username of the person you want to message. "
|
|
454
|
-
"Slack usernames are ALWAYS lowercase."
|
|
455
|
-
),
|
|
456
|
-
],
|
|
457
|
-
message: Annotated[str, "The message you want to send"],
|
|
458
|
-
) -> Annotated[dict, "The response from the Slack API"]:
|
|
459
|
-
"""Send a direct message to a user in Slack.
|
|
460
|
-
|
|
461
|
-
This tool is deprecated. Use `Slack.SendMessage` instead.
|
|
462
|
-
"""
|
|
463
|
-
return await send_message( # type: ignore[no-any-return]
|
|
464
|
-
context=context,
|
|
465
|
-
usernames=[user_name],
|
|
466
|
-
message=message,
|
|
467
|
-
)
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
@tool(
|
|
471
|
-
requires_auth=Slack(
|
|
472
|
-
scopes=[
|
|
473
|
-
"channels:read",
|
|
474
|
-
"groups:read",
|
|
475
|
-
"mpim:read",
|
|
476
|
-
"im:read",
|
|
477
|
-
"users:read",
|
|
478
|
-
"users:read.email",
|
|
479
|
-
"chat:write",
|
|
480
|
-
# "mpim:write",
|
|
481
|
-
"im:write",
|
|
482
|
-
],
|
|
483
|
-
)
|
|
484
|
-
)
|
|
485
|
-
async def send_message_to_channel(
|
|
486
|
-
context: ToolContext,
|
|
487
|
-
channel_name: Annotated[str, "The Slack channel name where you want to send the message. "],
|
|
488
|
-
message: Annotated[str, "The message you want to send"],
|
|
489
|
-
) -> Annotated[dict, "The response from the Slack API"]:
|
|
490
|
-
"""Send a message to a channel in Slack.
|
|
491
|
-
|
|
492
|
-
This tool is deprecated. Use `Slack.SendMessage` instead.
|
|
493
|
-
"""
|
|
494
|
-
return await send_message( # type: ignore[no-any-return]
|
|
495
|
-
context=context,
|
|
496
|
-
channel_name=channel_name,
|
|
497
|
-
message=message,
|
|
498
|
-
)
|
|
499
|
-
|
|
500
|
-
|
|
501
424
|
@tool(
|
|
502
425
|
requires_auth=Slack(
|
|
503
426
|
scopes=[
|
|
504
427
|
"channels:read",
|
|
505
428
|
"groups:read",
|
|
506
|
-
"
|
|
507
|
-
"
|
|
429
|
+
"channels:write",
|
|
430
|
+
"groups:write",
|
|
508
431
|
"users:read",
|
|
509
432
|
"users:read.email",
|
|
510
433
|
],
|
|
511
434
|
)
|
|
512
435
|
)
|
|
513
|
-
async def
|
|
514
|
-
context: ToolContext,
|
|
515
|
-
conversation_id: Annotated[str, "The ID of the conversation to get members for"],
|
|
516
|
-
limit: Annotated[int | None, "The maximum number of members to return."] = None,
|
|
517
|
-
next_cursor: Annotated[str | None, "The cursor to use for pagination."] = None,
|
|
518
|
-
) -> Annotated[dict, "Information about each member in the conversation"]:
|
|
519
|
-
"""Get the members of a conversation in Slack by the conversation's ID.
|
|
520
|
-
|
|
521
|
-
This tool is deprecated. Use the `Slack.GetUsersInConversation` tool instead.
|
|
522
|
-
"""
|
|
523
|
-
response = await get_users_in_conversation(
|
|
524
|
-
context=context,
|
|
525
|
-
conversation_id=conversation_id,
|
|
526
|
-
limit=limit,
|
|
527
|
-
next_cursor=next_cursor,
|
|
528
|
-
)
|
|
529
|
-
response["members"] = response["users"]
|
|
530
|
-
del response["users"]
|
|
531
|
-
return cast(dict, response)
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
@tool(
|
|
535
|
-
requires_auth=Slack(
|
|
536
|
-
scopes=[
|
|
537
|
-
"channels:read",
|
|
538
|
-
"groups:read",
|
|
539
|
-
"im:read",
|
|
540
|
-
"mpim:read",
|
|
541
|
-
"users:read",
|
|
542
|
-
"users:read.email",
|
|
543
|
-
],
|
|
544
|
-
)
|
|
545
|
-
)
|
|
546
|
-
async def get_members_in_channel_by_name(
|
|
547
|
-
context: ToolContext,
|
|
548
|
-
channel_name: Annotated[str, "The name of the channel to get members for"],
|
|
549
|
-
limit: Annotated[int | None, "The maximum number of members to return."] = None,
|
|
550
|
-
next_cursor: Annotated[str | None, "The cursor to use for pagination."] = None,
|
|
551
|
-
) -> Annotated[dict, "The channel members' IDs and Names"]:
|
|
552
|
-
"""Get the members of a conversation in Slack by the conversation's name.
|
|
553
|
-
|
|
554
|
-
This tool is deprecated. Use the `Slack.GetUsersInConversation` tool instead.
|
|
555
|
-
"""
|
|
556
|
-
response = await get_users_in_conversation(
|
|
557
|
-
context=context,
|
|
558
|
-
channel_name=channel_name,
|
|
559
|
-
limit=limit,
|
|
560
|
-
next_cursor=next_cursor,
|
|
561
|
-
)
|
|
562
|
-
response["members"] = response["users"]
|
|
563
|
-
del response["users"]
|
|
564
|
-
return cast(dict, response)
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
@tool(
|
|
568
|
-
requires_auth=Slack(
|
|
569
|
-
scopes=[
|
|
570
|
-
"channels:history",
|
|
571
|
-
"channels:read",
|
|
572
|
-
"groups:history",
|
|
573
|
-
"groups:read",
|
|
574
|
-
"im:history",
|
|
575
|
-
"im:read",
|
|
576
|
-
"mpim:history",
|
|
577
|
-
"mpim:read",
|
|
578
|
-
],
|
|
579
|
-
)
|
|
580
|
-
)
|
|
581
|
-
async def get_messages_in_channel_by_name(
|
|
582
|
-
context: ToolContext,
|
|
583
|
-
channel_name: Annotated[str, "The name of the channel"],
|
|
584
|
-
oldest_relative: Annotated[
|
|
585
|
-
str | None,
|
|
586
|
-
(
|
|
587
|
-
"The oldest message to include in the results, specified as a time offset from the "
|
|
588
|
-
"current time in the format 'DD:HH:MM'"
|
|
589
|
-
),
|
|
590
|
-
] = None,
|
|
591
|
-
latest_relative: Annotated[
|
|
592
|
-
str | None,
|
|
593
|
-
(
|
|
594
|
-
"The latest message to include in the results, specified as a time offset from the "
|
|
595
|
-
"current time in the format 'DD:HH:MM'"
|
|
596
|
-
),
|
|
597
|
-
] = None,
|
|
598
|
-
oldest_datetime: Annotated[
|
|
599
|
-
str | None,
|
|
600
|
-
(
|
|
601
|
-
"The oldest message to include in the results, specified as a datetime object in the "
|
|
602
|
-
"format 'YYYY-MM-DD HH:MM:SS'"
|
|
603
|
-
),
|
|
604
|
-
] = None,
|
|
605
|
-
latest_datetime: Annotated[
|
|
606
|
-
str | None,
|
|
607
|
-
(
|
|
608
|
-
"The latest message to include in the results, specified as a datetime object in the "
|
|
609
|
-
"format 'YYYY-MM-DD HH:MM:SS'"
|
|
610
|
-
),
|
|
611
|
-
] = None,
|
|
612
|
-
limit: Annotated[int | None, "The maximum number of messages to return."] = None,
|
|
613
|
-
next_cursor: Annotated[str | None, "The cursor to use for pagination."] = None,
|
|
614
|
-
) -> Annotated[
|
|
615
|
-
dict,
|
|
616
|
-
(
|
|
617
|
-
"The messages in a channel and next cursor for paginating results (when "
|
|
618
|
-
"there are additional messages to retrieve)."
|
|
619
|
-
),
|
|
620
|
-
]:
|
|
621
|
-
"""Get the messages in a channel by the channel's name.
|
|
622
|
-
|
|
623
|
-
This tool is deprecated. Use the `Slack.GetMessages` tool instead.
|
|
624
|
-
|
|
625
|
-
To filter messages by an absolute datetime, use 'oldest_datetime' and/or 'latest_datetime'. If
|
|
626
|
-
only 'oldest_datetime' is provided, it will return messages from the oldest_datetime to the
|
|
627
|
-
current time. If only 'latest_datetime' is provided, it will return messages since the
|
|
628
|
-
beginning of the channel to the latest_datetime.
|
|
629
|
-
|
|
630
|
-
To filter messages by a relative datetime (e.g. 3 days ago, 1 hour ago, etc.), use
|
|
631
|
-
'oldest_relative' and/or 'latest_relative'. If only 'oldest_relative' is provided, it will
|
|
632
|
-
return messages from the oldest_relative to the current time. If only 'latest_relative' is
|
|
633
|
-
provided, it will return messages from the current time to the latest_relative.
|
|
634
|
-
|
|
635
|
-
Do not provide both 'oldest_datetime' and 'oldest_relative' or both 'latest_datetime' and
|
|
636
|
-
'latest_relative'.
|
|
637
|
-
|
|
638
|
-
Leave all arguments with the default None to get messages without date/time filtering"""
|
|
639
|
-
return await get_messages( # type: ignore[no-any-return]
|
|
640
|
-
context=context,
|
|
641
|
-
channel_name=channel_name,
|
|
642
|
-
oldest_relative=oldest_relative,
|
|
643
|
-
latest_relative=latest_relative,
|
|
644
|
-
oldest_datetime=oldest_datetime,
|
|
645
|
-
latest_datetime=latest_datetime,
|
|
646
|
-
limit=limit,
|
|
647
|
-
next_cursor=next_cursor,
|
|
648
|
-
)
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
@tool(
|
|
652
|
-
requires_auth=Slack(
|
|
653
|
-
scopes=["channels:history", "groups:history", "im:history", "mpim:history"],
|
|
654
|
-
)
|
|
655
|
-
)
|
|
656
|
-
async def get_messages_in_conversation_by_id(
|
|
436
|
+
async def invite_users_to_channel(
|
|
657
437
|
context: ToolContext,
|
|
658
|
-
|
|
659
|
-
oldest_relative: Annotated[
|
|
438
|
+
channel_id: Annotated[
|
|
660
439
|
str | None,
|
|
661
|
-
(
|
|
662
|
-
|
|
663
|
-
"current time in the format 'DD:HH:MM'"
|
|
664
|
-
),
|
|
440
|
+
"The ID of the Slack channel or MPIM (multi-person direct message) to invite users to. "
|
|
441
|
+
"Provide exactly one of channel_id OR channel_name.",
|
|
665
442
|
] = None,
|
|
666
|
-
|
|
667
|
-
str | None,
|
|
668
|
-
(
|
|
669
|
-
"The latest message to include in the results, specified as a time offset from the "
|
|
670
|
-
"current time in the format 'DD:HH:MM'"
|
|
671
|
-
),
|
|
672
|
-
] = None,
|
|
673
|
-
oldest_datetime: Annotated[
|
|
674
|
-
str | None,
|
|
675
|
-
(
|
|
676
|
-
"The oldest message to include in the results, specified as a datetime object in the "
|
|
677
|
-
"format 'YYYY-MM-DD HH:MM:SS'"
|
|
678
|
-
),
|
|
679
|
-
] = None,
|
|
680
|
-
latest_datetime: Annotated[
|
|
681
|
-
str | None,
|
|
682
|
-
(
|
|
683
|
-
"The latest message to include in the results, specified as a datetime object in the "
|
|
684
|
-
"format 'YYYY-MM-DD HH:MM:SS'"
|
|
685
|
-
),
|
|
686
|
-
] = None,
|
|
687
|
-
limit: Annotated[int | None, "The maximum number of messages to return."] = None,
|
|
688
|
-
next_cursor: Annotated[str | None, "The cursor to use for pagination."] = None,
|
|
689
|
-
) -> Annotated[
|
|
690
|
-
dict,
|
|
691
|
-
(
|
|
692
|
-
"The messages in a conversation and next cursor for paginating results (when "
|
|
693
|
-
"there are additional messages to retrieve)."
|
|
694
|
-
),
|
|
695
|
-
]:
|
|
696
|
-
"""Get the messages in a conversation by the conversation's ID.
|
|
697
|
-
|
|
698
|
-
This tool is deprecated. Use the 'Slack.GetMessages' tool instead.
|
|
699
|
-
|
|
700
|
-
A conversation can be a channel, a DM, or a group DM.
|
|
701
|
-
|
|
702
|
-
To filter by an absolute datetime, use 'oldest_datetime' and/or 'latest_datetime'. If
|
|
703
|
-
only 'oldest_datetime' is provided, it returns messages from the oldest_datetime to the
|
|
704
|
-
current time. If only 'latest_datetime' is provided, it returns messages since the
|
|
705
|
-
beginning of the conversation to the latest_datetime.
|
|
706
|
-
|
|
707
|
-
To filter by a relative datetime (e.g. 3 days ago, 1 hour ago, etc.), use
|
|
708
|
-
'oldest_relative' and/or 'latest_relative'. If only 'oldest_relative' is provided, it returns
|
|
709
|
-
messages from the oldest_relative to the current time. If only 'latest_relative' is provided,
|
|
710
|
-
it returns messages from the current time to the latest_relative.
|
|
711
|
-
|
|
712
|
-
Do not provide both 'oldest_datetime' and 'oldest_relative' or both 'latest_datetime' and
|
|
713
|
-
'latest_relative'.
|
|
714
|
-
|
|
715
|
-
Leave all arguments with the default None to get messages without date/time filtering"""
|
|
716
|
-
return await get_messages( # type: ignore[no-any-return]
|
|
717
|
-
context=context,
|
|
718
|
-
conversation_id=conversation_id,
|
|
719
|
-
oldest_relative=oldest_relative,
|
|
720
|
-
latest_relative=latest_relative,
|
|
721
|
-
oldest_datetime=oldest_datetime,
|
|
722
|
-
latest_datetime=latest_datetime,
|
|
723
|
-
limit=limit,
|
|
724
|
-
next_cursor=next_cursor,
|
|
725
|
-
)
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
@tool(requires_auth=Slack(scopes=["im:history", "im:read", "users:read", "users:read.email"]))
|
|
729
|
-
async def get_messages_in_direct_message_conversation_by_username(
|
|
730
|
-
context: ToolContext,
|
|
731
|
-
username: Annotated[str, "The username of the user to get messages from"],
|
|
732
|
-
oldest_relative: Annotated[
|
|
443
|
+
channel_name: Annotated[
|
|
733
444
|
str | None,
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
),
|
|
445
|
+
"The name of the channel to invite users to. Prefer providing a channel_id when "
|
|
446
|
+
"available for better performance. Note: MPIMs don't have names, so use channel_id "
|
|
447
|
+
"for MPIMs.",
|
|
738
448
|
] = None,
|
|
739
|
-
|
|
740
|
-
str | None,
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
"current time in the format 'DD:HH:MM'"
|
|
744
|
-
),
|
|
449
|
+
user_ids: Annotated[
|
|
450
|
+
list[str] | None,
|
|
451
|
+
"The Slack user IDs of the people to invite. Up to 100 users may be listed. "
|
|
452
|
+
"Provide at least one of user_ids, usernames, or emails.",
|
|
745
453
|
] = None,
|
|
746
|
-
|
|
747
|
-
str | None,
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
"format 'YYYY-MM-DD HH:MM:SS'"
|
|
751
|
-
),
|
|
454
|
+
usernames: Annotated[
|
|
455
|
+
list[str] | None,
|
|
456
|
+
"The Slack usernames of the people to invite. Prefer providing user_ids "
|
|
457
|
+
"and/or emails when available for better performance.",
|
|
752
458
|
] = None,
|
|
753
|
-
|
|
754
|
-
str | None,
|
|
755
|
-
|
|
756
|
-
"The latest message to include in the results, specified as a datetime object in the "
|
|
757
|
-
"format 'YYYY-MM-DD HH:MM:SS'"
|
|
758
|
-
),
|
|
459
|
+
emails: Annotated[
|
|
460
|
+
list[str] | None,
|
|
461
|
+
"The email addresses of the people to invite.",
|
|
759
462
|
] = None,
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
) -> Annotated[
|
|
763
|
-
dict,
|
|
764
|
-
(
|
|
765
|
-
"The messages in a direct message conversation and next cursor for paginating results "
|
|
766
|
-
"when there are additional messages to retrieve."
|
|
767
|
-
),
|
|
768
|
-
]:
|
|
769
|
-
"""Get the messages in a direct conversation by the user's name.
|
|
463
|
+
) -> Annotated[dict, "The response from inviting users to the conversation"]:
|
|
464
|
+
"""Invite users to a Slack channel or MPIM (multi-person direct message).
|
|
770
465
|
|
|
771
|
-
This tool
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
usernames=[username],
|
|
776
|
-
oldest_relative=oldest_relative,
|
|
777
|
-
latest_relative=latest_relative,
|
|
778
|
-
oldest_datetime=oldest_datetime,
|
|
779
|
-
latest_datetime=latest_datetime,
|
|
780
|
-
limit=limit,
|
|
781
|
-
next_cursor=next_cursor,
|
|
782
|
-
)
|
|
466
|
+
This tool invites specified users to join a Slack conversation. It works with:
|
|
467
|
+
- Public channels
|
|
468
|
+
- Private channels
|
|
469
|
+
- MPIMs (multi-person direct messages / group DMs)
|
|
783
470
|
|
|
471
|
+
You can specify users by their user IDs, usernames, or email addresses.
|
|
784
472
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
context: ToolContext,
|
|
788
|
-
usernames: Annotated[list[str], "The usernames of the users to get messages from"],
|
|
789
|
-
oldest_relative: Annotated[
|
|
790
|
-
str | None,
|
|
791
|
-
(
|
|
792
|
-
"The oldest message to include in the results, specified as a time offset from the "
|
|
793
|
-
"current time in the format 'DD:HH:MM'"
|
|
794
|
-
),
|
|
795
|
-
] = None,
|
|
796
|
-
latest_relative: Annotated[
|
|
797
|
-
str | None,
|
|
798
|
-
(
|
|
799
|
-
"The latest message to include in the results, specified as a time offset from the "
|
|
800
|
-
"current time in the format 'DD:HH:MM'"
|
|
801
|
-
),
|
|
802
|
-
] = None,
|
|
803
|
-
oldest_datetime: Annotated[
|
|
804
|
-
str | None,
|
|
805
|
-
(
|
|
806
|
-
"The oldest message to include in the results, specified as a datetime object in the "
|
|
807
|
-
"format 'YYYY-MM-DD HH:MM:SS'"
|
|
808
|
-
),
|
|
809
|
-
] = None,
|
|
810
|
-
latest_datetime: Annotated[
|
|
811
|
-
str | None,
|
|
812
|
-
(
|
|
813
|
-
"The latest message to include in the results, specified as a datetime object in the "
|
|
814
|
-
"format 'YYYY-MM-DD HH:MM:SS'"
|
|
815
|
-
),
|
|
816
|
-
] = None,
|
|
817
|
-
limit: Annotated[int | None, "The maximum number of messages to return."] = None,
|
|
818
|
-
next_cursor: Annotated[str | None, "The cursor to use for pagination."] = None,
|
|
819
|
-
) -> Annotated[
|
|
820
|
-
dict,
|
|
821
|
-
(
|
|
822
|
-
"The messages in a multi-person direct message conversation and next cursor for "
|
|
823
|
-
"paginating results (when there are additional messages to retrieve)."
|
|
824
|
-
),
|
|
825
|
-
]:
|
|
826
|
-
"""Get the messages in a multi-person direct message conversation by the usernames.
|
|
473
|
+
Provide exactly one of channel_id or channel_name, and at least one of user_ids, usernames,
|
|
474
|
+
or emails.
|
|
827
475
|
|
|
828
|
-
|
|
476
|
+
The tool will resolve usernames and emails to user IDs before inviting them.
|
|
477
|
+
Up to 100 users may be invited at once.
|
|
829
478
|
"""
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
oldest_relative=oldest_relative,
|
|
834
|
-
latest_relative=latest_relative,
|
|
835
|
-
oldest_datetime=oldest_datetime,
|
|
836
|
-
latest_datetime=latest_datetime,
|
|
837
|
-
limit=limit,
|
|
838
|
-
next_cursor=next_cursor,
|
|
839
|
-
)
|
|
479
|
+
# XOR validation: exactly one of channel_id or channel_name must be provided
|
|
480
|
+
if not ((channel_id is None) ^ (channel_name is None)):
|
|
481
|
+
raise ToolExecutionError("Provide exactly one of channel_id OR channel_name.")
|
|
840
482
|
|
|
483
|
+
if not any([user_ids, usernames, emails]):
|
|
484
|
+
raise ToolExecutionError(
|
|
485
|
+
"Provide at least one of user_ids, usernames, or emails to invite."
|
|
486
|
+
)
|
|
841
487
|
|
|
842
|
-
|
|
843
|
-
requires_auth=Slack(
|
|
844
|
-
scopes=["channels:read", "groups:read", "im:read", "mpim:read"],
|
|
845
|
-
)
|
|
846
|
-
)
|
|
847
|
-
async def list_conversations_metadata(
|
|
848
|
-
context: ToolContext,
|
|
849
|
-
conversation_types: Annotated[
|
|
850
|
-
list[ConversationType] | None,
|
|
851
|
-
"Optionally filter by the type(s) of conversations. Defaults to None (all types).",
|
|
852
|
-
] = None,
|
|
853
|
-
limit: Annotated[int | None, "The maximum number of conversations to list."] = None,
|
|
854
|
-
next_cursor: Annotated[str | None, "The cursor to use for pagination."] = None,
|
|
855
|
-
) -> Annotated[dict, "The list of conversations found with metadata"]:
|
|
856
|
-
"""
|
|
857
|
-
List Slack conversations (channels, DMs, MPIMs) the user is a member of.
|
|
488
|
+
auth_token = context.get_auth_token_or_empty()
|
|
858
489
|
|
|
859
|
-
|
|
490
|
+
# Resolve channel name to ID if needed
|
|
491
|
+
resolved_channel_id = channel_id
|
|
492
|
+
if not resolved_channel_id:
|
|
493
|
+
channel = await get_channel_by_name(auth_token, cast(str, channel_name))
|
|
494
|
+
resolved_channel_id = channel["id"]
|
|
860
495
|
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
will release too much CO2 in the atmosphere and contribute to global warming.
|
|
864
|
-
"""
|
|
865
|
-
return await list_conversations( # type: ignore[no-any-return]
|
|
496
|
+
# Use the shared helper to invite users
|
|
497
|
+
invite_result = await invite_users_to_conversation(
|
|
866
498
|
context=context,
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
@tool(
|
|
874
|
-
requires_auth=Slack(
|
|
875
|
-
scopes=["channels:read"],
|
|
876
|
-
)
|
|
877
|
-
)
|
|
878
|
-
async def list_public_channels_metadata(
|
|
879
|
-
context: ToolContext,
|
|
880
|
-
limit: Annotated[int | None, "The maximum number of channels to list."] = None,
|
|
881
|
-
) -> Annotated[dict, "The public channels"]:
|
|
882
|
-
"""List metadata for public channels in Slack that the user is a member of.
|
|
883
|
-
|
|
884
|
-
This tool is deprecated. Use the `Slack.ListConversations` tool instead.
|
|
885
|
-
"""
|
|
886
|
-
return await list_conversations( # type: ignore[no-any-return]
|
|
887
|
-
context,
|
|
888
|
-
conversation_types=[ConversationType.PUBLIC_CHANNEL],
|
|
889
|
-
limit=limit,
|
|
890
|
-
)
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
@tool(
|
|
894
|
-
requires_auth=Slack(
|
|
895
|
-
scopes=["groups:read"],
|
|
896
|
-
)
|
|
897
|
-
)
|
|
898
|
-
async def list_private_channels_metadata(
|
|
899
|
-
context: ToolContext,
|
|
900
|
-
limit: Annotated[int | None, "The maximum number of channels to list."] = None,
|
|
901
|
-
) -> Annotated[dict, "The private channels"]:
|
|
902
|
-
"""List metadata for private channels in Slack that the user is a member of.
|
|
903
|
-
|
|
904
|
-
This tool is deprecated. Use the `Slack.ListConversations` tool instead.
|
|
905
|
-
"""
|
|
906
|
-
return await list_conversations( # type: ignore[no-any-return]
|
|
907
|
-
context,
|
|
908
|
-
conversation_types=[ConversationType.PRIVATE_CHANNEL],
|
|
909
|
-
limit=limit,
|
|
910
|
-
)
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
@tool(
|
|
914
|
-
requires_auth=Slack(
|
|
915
|
-
scopes=["mpim:read"],
|
|
916
|
-
)
|
|
917
|
-
)
|
|
918
|
-
async def list_group_direct_message_conversations_metadata(
|
|
919
|
-
context: ToolContext,
|
|
920
|
-
limit: Annotated[int | None, "The maximum number of conversations to list."] = None,
|
|
921
|
-
) -> Annotated[dict, "The group direct message conversations metadata"]:
|
|
922
|
-
"""List metadata for group direct message conversations that the user is a member of.
|
|
923
|
-
|
|
924
|
-
This tool is deprecated. Use the `Slack.ListConversations` tool instead.
|
|
925
|
-
"""
|
|
926
|
-
return await list_conversations( # type: ignore[no-any-return]
|
|
927
|
-
context,
|
|
928
|
-
conversation_types=[ConversationType.MULTI_PERSON_DIRECT_MESSAGE],
|
|
929
|
-
limit=limit,
|
|
930
|
-
)
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
# Note: Bots are included in the results.
|
|
934
|
-
# Note: Direct messages with no conversation history are included in the results.
|
|
935
|
-
@tool(
|
|
936
|
-
requires_auth=Slack(
|
|
937
|
-
scopes=["im:read"],
|
|
938
|
-
)
|
|
939
|
-
)
|
|
940
|
-
async def list_direct_message_conversations_metadata(
|
|
941
|
-
context: ToolContext,
|
|
942
|
-
limit: Annotated[int | None, "The maximum number of conversations to list."] = None,
|
|
943
|
-
) -> Annotated[dict, "The direct message conversations metadata"]:
|
|
944
|
-
"""List metadata for direct message conversations in Slack that the user is a member of.
|
|
945
|
-
|
|
946
|
-
This tool is deprecated. Use the `Slack.ListConversations` tool instead.
|
|
947
|
-
"""
|
|
948
|
-
return await list_conversations( # type: ignore[no-any-return]
|
|
949
|
-
context,
|
|
950
|
-
conversation_types=[ConversationType.DIRECT_MESSAGE],
|
|
951
|
-
limit=limit,
|
|
952
|
-
)
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
@tool(
|
|
956
|
-
requires_auth=Slack(
|
|
957
|
-
scopes=[
|
|
958
|
-
"channels:read",
|
|
959
|
-
"groups:read",
|
|
960
|
-
"mpim:read",
|
|
961
|
-
"im:read",
|
|
962
|
-
"users:read",
|
|
963
|
-
"users:read.email",
|
|
964
|
-
],
|
|
965
|
-
)
|
|
966
|
-
)
|
|
967
|
-
async def get_conversation_metadata_by_id(
|
|
968
|
-
context: ToolContext,
|
|
969
|
-
conversation_id: Annotated[str, "The ID of the conversation to get metadata for"],
|
|
970
|
-
) -> Annotated[dict, "The conversation metadata"]:
|
|
971
|
-
"""Get the metadata of a conversation in Slack searching by its ID.
|
|
972
|
-
|
|
973
|
-
This tool is deprecated. Use the `Slack.GetConversationMetadata` tool instead.
|
|
974
|
-
"""
|
|
975
|
-
return await get_conversation_metadata(context, conversation_id=conversation_id) # type: ignore[no-any-return]
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
@tool(
|
|
979
|
-
requires_auth=Slack(
|
|
980
|
-
scopes=[
|
|
981
|
-
"channels:read",
|
|
982
|
-
"groups:read",
|
|
983
|
-
"mpim:read",
|
|
984
|
-
"im:read",
|
|
985
|
-
"users:read",
|
|
986
|
-
"users:read.email",
|
|
987
|
-
],
|
|
499
|
+
conversation_id=cast(str, resolved_channel_id),
|
|
500
|
+
user_ids=user_ids,
|
|
501
|
+
usernames=usernames,
|
|
502
|
+
emails=emails,
|
|
988
503
|
)
|
|
989
|
-
)
|
|
990
|
-
async def get_channel_metadata_by_name(
|
|
991
|
-
context: ToolContext,
|
|
992
|
-
channel_name: Annotated[str, "The name of the channel to get metadata for"],
|
|
993
|
-
# We kept the `next_cursor` argument for backwards compatibility, but it isn't actually used,
|
|
994
|
-
# since this tool never really paginates.
|
|
995
|
-
next_cursor: Annotated[
|
|
996
|
-
str | None,
|
|
997
|
-
"The cursor to use for pagination, if continuing from a previous search.",
|
|
998
|
-
] = None,
|
|
999
|
-
) -> Annotated[dict, "The channel metadata"]:
|
|
1000
|
-
"""Get the metadata of a channel in Slack searching by its name.
|
|
1001
|
-
|
|
1002
|
-
This tool is deprecated. Use the `Slack.GetConversationMetadata` tool instead."""
|
|
1003
|
-
return await get_conversation_metadata(context, channel_name=channel_name) # type: ignore[no-any-return]
|
|
1004
504
|
|
|
505
|
+
invited_channel = invite_result.get("channel", {})
|
|
506
|
+
channel_display = invited_channel.get("name", resolved_channel_id)
|
|
507
|
+
message = f"Successfully invited {invite_result['invited_count']} user(s) to {channel_display}"
|
|
1005
508
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
"users:read.email",
|
|
1015
|
-
],
|
|
1016
|
-
)
|
|
1017
|
-
)
|
|
1018
|
-
async def get_direct_message_conversation_metadata_by_username(
|
|
1019
|
-
context: ToolContext,
|
|
1020
|
-
username: Annotated[str, "The username of the user/person to get messages with"],
|
|
1021
|
-
# We kept the `next_cursor` argument for backwards compatibility, but it isn't actually used,
|
|
1022
|
-
# since this tool never really paginates.
|
|
1023
|
-
next_cursor: Annotated[
|
|
1024
|
-
str | None,
|
|
1025
|
-
"The cursor to use for pagination, if continuing from a previous search.",
|
|
1026
|
-
] = None,
|
|
1027
|
-
) -> Annotated[
|
|
1028
|
-
dict | None,
|
|
1029
|
-
"The direct message conversation metadata.",
|
|
1030
|
-
]:
|
|
1031
|
-
"""Get the metadata of a direct message conversation in Slack by the username.
|
|
1032
|
-
|
|
1033
|
-
This tool is deprecated. Use the `Slack.GetConversationMetadata` tool instead."""
|
|
1034
|
-
return await get_conversation_metadata(context, usernames=[username]) # type: ignore[no-any-return]
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
@tool(
|
|
1038
|
-
requires_auth=Slack(
|
|
1039
|
-
scopes=[
|
|
1040
|
-
"channels:read",
|
|
1041
|
-
"groups:read",
|
|
1042
|
-
"mpim:read",
|
|
1043
|
-
"im:read",
|
|
1044
|
-
"users:read",
|
|
1045
|
-
"users:read.email",
|
|
1046
|
-
],
|
|
1047
|
-
)
|
|
1048
|
-
)
|
|
1049
|
-
async def get_multi_person_dm_conversation_metadata_by_usernames(
|
|
1050
|
-
context: ToolContext,
|
|
1051
|
-
usernames: Annotated[list[str], "The usernames of the users/people to get messages with"],
|
|
1052
|
-
# We kept the `next_cursor` argument for backwards compatibility, but it isn't actually used,
|
|
1053
|
-
# since this tool never really paginates.
|
|
1054
|
-
next_cursor: Annotated[
|
|
1055
|
-
str | None,
|
|
1056
|
-
"The cursor to use for pagination, if continuing from a previous search.",
|
|
1057
|
-
] = None,
|
|
1058
|
-
) -> Annotated[
|
|
1059
|
-
dict | None,
|
|
1060
|
-
"The multi-person direct message conversation metadata.",
|
|
1061
|
-
]:
|
|
1062
|
-
"""Get the metadata of a multi-person direct message conversation in Slack by the usernames.
|
|
1063
|
-
|
|
1064
|
-
This tool is deprecated. Use the `Slack.GetConversationMetadata` tool instead."""
|
|
1065
|
-
return await get_conversation_metadata(context, usernames=usernames) # type: ignore[no-any-return]
|
|
509
|
+
return {
|
|
510
|
+
"success": True,
|
|
511
|
+
"channel_id": resolved_channel_id,
|
|
512
|
+
"channel_name": invited_channel.get("name"),
|
|
513
|
+
"invited_user_ids": invite_result["invited_user_ids"],
|
|
514
|
+
"invited_count": invite_result["invited_count"],
|
|
515
|
+
"message": message,
|
|
516
|
+
}
|
arcade_slack/tools/users.py
CHANGED
|
@@ -82,18 +82,3 @@ async def list_users(
|
|
|
82
82
|
]
|
|
83
83
|
|
|
84
84
|
return {"users": users, "next_cursor": next_cursor}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
# NOTE: This tool is kept here for backwards compatibility.
|
|
88
|
-
# Use the `Slack.GetUsersInfo` tool instead.
|
|
89
|
-
@tool(requires_auth=Slack(scopes=["users:read", "users:read.email"]))
|
|
90
|
-
async def get_user_info_by_id(
|
|
91
|
-
context: ToolContext,
|
|
92
|
-
user_id: Annotated[str, "The ID of the user to get"],
|
|
93
|
-
) -> Annotated[dict[str, Any], "The user's information"]:
|
|
94
|
-
"""Get the information of a user in Slack.
|
|
95
|
-
|
|
96
|
-
This tool is deprecated. Use the `Slack.GetUsersInfo` tool instead.
|
|
97
|
-
"""
|
|
98
|
-
users = await get_users_info(context, user_ids=[user_id])
|
|
99
|
-
return cast(dict[str, Any], users["users"][0])
|
arcade_slack/user_retrieval.py
CHANGED
|
@@ -2,7 +2,7 @@ import asyncio
|
|
|
2
2
|
from typing import Any, cast
|
|
3
3
|
|
|
4
4
|
from arcade_tdk import ToolContext
|
|
5
|
-
from arcade_tdk.errors import
|
|
5
|
+
from arcade_tdk.errors import FatalToolError
|
|
6
6
|
from slack_sdk.errors import SlackApiError
|
|
7
7
|
from slack_sdk.web.async_client import AsyncWebClient
|
|
8
8
|
|
|
@@ -43,7 +43,7 @@ async def get_users_by_id_username_or_email(
|
|
|
43
43
|
emails = [emails]
|
|
44
44
|
|
|
45
45
|
if not any([user_ids, usernames, emails]):
|
|
46
|
-
raise
|
|
46
|
+
raise FatalToolError("At least one of user_ids, usernames, or emails must be provided")
|
|
47
47
|
|
|
48
48
|
if not semaphore:
|
|
49
49
|
semaphore = asyncio.Semaphore(MAX_CONCURRENT_REQUESTS)
|
|
@@ -179,7 +179,7 @@ async def get_users_by_email(
|
|
|
179
179
|
|
|
180
180
|
for email in emails:
|
|
181
181
|
if not is_valid_email(email):
|
|
182
|
-
raise
|
|
182
|
+
raise FatalToolError(f"Invalid email address: {email}")
|
|
183
183
|
|
|
184
184
|
if not semaphore:
|
|
185
185
|
semaphore = asyncio.Semaphore(MAX_CONCURRENT_REQUESTS)
|
arcade_slack/utils.py
CHANGED
|
@@ -7,7 +7,8 @@ from datetime import datetime, timezone
|
|
|
7
7
|
from typing import Any, cast
|
|
8
8
|
|
|
9
9
|
from arcade_tdk import ToolContext
|
|
10
|
-
from arcade_tdk.errors import RetryableToolError
|
|
10
|
+
from arcade_tdk.errors import RetryableToolError, ToolExecutionError
|
|
11
|
+
from slack_sdk.web.async_client import AsyncWebClient
|
|
11
12
|
|
|
12
13
|
from arcade_slack.constants import (
|
|
13
14
|
MAX_CONCURRENT_REQUESTS,
|
|
@@ -569,7 +570,7 @@ async def populate_users_in_messages(auth_token: str, messages: list[dict]) -> l
|
|
|
569
570
|
reaction["users"] = reaction_users
|
|
570
571
|
# If any data is missing, just leave the message as it is
|
|
571
572
|
except Exception as exc:
|
|
572
|
-
logger.exception(exc)
|
|
573
|
+
logger.exception(exc)
|
|
573
574
|
|
|
574
575
|
return messages
|
|
575
576
|
|
|
@@ -613,3 +614,114 @@ def get_user_ids_from_messages(messages: list[dict]) -> list[str]:
|
|
|
613
614
|
user_ids.extend(reaction.get("users", []))
|
|
614
615
|
|
|
615
616
|
return user_ids
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
def format_invite_errors(errors: Any) -> str:
|
|
620
|
+
"""Format error messages from Slack invite API partial errors."""
|
|
621
|
+
if isinstance(errors, list):
|
|
622
|
+
formatted_errors = []
|
|
623
|
+
for error in errors:
|
|
624
|
+
if isinstance(error, dict):
|
|
625
|
+
error_code = error.get("error") or error.get("code") or error.get("message")
|
|
626
|
+
user_id = error.get("user") or error.get("user_id")
|
|
627
|
+
if error_code and user_id:
|
|
628
|
+
formatted_errors.append(f"{error_code} ({user_id})")
|
|
629
|
+
elif error_code:
|
|
630
|
+
formatted_errors.append(str(error_code))
|
|
631
|
+
elif user_id:
|
|
632
|
+
formatted_errors.append(f"unknown_error ({user_id})")
|
|
633
|
+
else:
|
|
634
|
+
formatted_errors.append(str(error))
|
|
635
|
+
else:
|
|
636
|
+
formatted_errors.append(str(error))
|
|
637
|
+
if formatted_errors:
|
|
638
|
+
return ", ".join(formatted_errors)
|
|
639
|
+
|
|
640
|
+
return str(errors)
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
def raise_for_invite_errors(errors: Any, conversation_id: str | None) -> None:
|
|
644
|
+
"""Raise ToolExecutionError for partial invite errors from a 200 response.
|
|
645
|
+
|
|
646
|
+
Slack's conversations.invite API can return ok: true with an errors array
|
|
647
|
+
for partial failures. This function handles those cases.
|
|
648
|
+
"""
|
|
649
|
+
if not errors:
|
|
650
|
+
return
|
|
651
|
+
|
|
652
|
+
error_message = format_invite_errors(errors)
|
|
653
|
+
raise ToolExecutionError(f"Failed to invite some users to conversation: {error_message}")
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
async def invite_users_to_conversation(
|
|
657
|
+
context: ToolContext,
|
|
658
|
+
conversation_id: str,
|
|
659
|
+
user_ids: list[str] | None = None,
|
|
660
|
+
usernames: list[str] | None = None,
|
|
661
|
+
emails: list[str] | None = None,
|
|
662
|
+
) -> dict[str, Any]:
|
|
663
|
+
"""Internal helper to invite users to a conversation (channel or MPIM).
|
|
664
|
+
|
|
665
|
+
This function handles the core logic of resolving users and inviting them.
|
|
666
|
+
It does not wrap errors in try/except - SlackApiError exceptions will bubble
|
|
667
|
+
up to be handled by the SlackErrorAdapter.
|
|
668
|
+
|
|
669
|
+
Args:
|
|
670
|
+
context: The tool context
|
|
671
|
+
conversation_id: The ID of the conversation to invite users to
|
|
672
|
+
user_ids: Optional list of Slack user IDs
|
|
673
|
+
usernames: Optional list of Slack usernames
|
|
674
|
+
emails: Optional list of email addresses
|
|
675
|
+
|
|
676
|
+
Returns:
|
|
677
|
+
A dict with invited_user_ids and invited_count
|
|
678
|
+
|
|
679
|
+
Raises:
|
|
680
|
+
ToolExecutionError: If no valid users found or if partial errors occur
|
|
681
|
+
"""
|
|
682
|
+
from arcade_slack.user_retrieval import get_users_by_id_username_or_email
|
|
683
|
+
|
|
684
|
+
# Resolve usernames and emails to user IDs
|
|
685
|
+
resolved_user_ids = user_ids.copy() if user_ids else []
|
|
686
|
+
|
|
687
|
+
if usernames or emails:
|
|
688
|
+
users = await get_users_by_id_username_or_email(
|
|
689
|
+
context=context,
|
|
690
|
+
usernames=usernames,
|
|
691
|
+
emails=emails,
|
|
692
|
+
)
|
|
693
|
+
resolved_user_ids.extend([user["id"] for user in users])
|
|
694
|
+
|
|
695
|
+
if not resolved_user_ids:
|
|
696
|
+
raise ToolExecutionError("No valid users found to invite to the conversation.")
|
|
697
|
+
|
|
698
|
+
# Remove duplicates
|
|
699
|
+
resolved_user_ids = list(set(resolved_user_ids))
|
|
700
|
+
|
|
701
|
+
# Limit to 100 users per Slack API requirements
|
|
702
|
+
if len(resolved_user_ids) > 100:
|
|
703
|
+
user_count = len(resolved_user_ids)
|
|
704
|
+
raise ToolExecutionError(
|
|
705
|
+
f"Cannot invite more than 100 users at once. You provided {user_count} users."
|
|
706
|
+
)
|
|
707
|
+
|
|
708
|
+
slack_client = AsyncWebClient(token=context.get_auth_token_or_empty())
|
|
709
|
+
|
|
710
|
+
# Slack expects a comma-separated string of user IDs
|
|
711
|
+
users_str = ",".join(resolved_user_ids)
|
|
712
|
+
response = await slack_client.conversations_invite(
|
|
713
|
+
channel=conversation_id,
|
|
714
|
+
users=users_str,
|
|
715
|
+
)
|
|
716
|
+
|
|
717
|
+
response_data = cast(dict[str, Any], response.data)
|
|
718
|
+
|
|
719
|
+
# Handle partial errors (200 response with errors array)
|
|
720
|
+
invite_errors = response_data.get("errors")
|
|
721
|
+
raise_for_invite_errors(invite_errors, conversation_id)
|
|
722
|
+
|
|
723
|
+
return {
|
|
724
|
+
"invited_user_ids": resolved_user_ids,
|
|
725
|
+
"invited_count": len(resolved_user_ids),
|
|
726
|
+
"channel": response_data.get("channel", {}),
|
|
727
|
+
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
arcade_slack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
arcade_slack/constants.py,sha256=ANAZOmNSqrbZHDqEvQfau7_91if9EeKV-G5D0VBB9vo,524
|
|
3
3
|
arcade_slack/conversation_retrieval.py,sha256=VKc0Cc0k4UZ0OON_1l-HxWRzk_nSCzgoP5lgGyUxLFs,1902
|
|
4
|
-
arcade_slack/critics.py,sha256=
|
|
4
|
+
arcade_slack/critics.py,sha256=ZP3jxptwA-8hubUBdhO4cxHrtf_DUAcYt0-TVCXF2AQ,1200
|
|
5
5
|
arcade_slack/custom_types.py,sha256=-23JnfXjMQ-H8CyRL3CEv9opPMySox1KINH5rrPIOt0,928
|
|
6
6
|
arcade_slack/exceptions.py,sha256=YQ4CTa1LbR-G7sjnQM8LB7LruxZDqPzvo-cptFYW7E8,385
|
|
7
|
-
arcade_slack/message_retrieval.py,sha256=
|
|
7
|
+
arcade_slack/message_retrieval.py,sha256=ZSspuVfM0yeMMwMFL_M7DeoPnLnUgX_N4_eNPGc4oKk,2488
|
|
8
8
|
arcade_slack/models.py,sha256=R0dze0YMQW_v_GqarA2F3ZMR3ueN_ant9K855N9uqlE,11958
|
|
9
|
-
arcade_slack/user_retrieval.py,sha256=
|
|
10
|
-
arcade_slack/utils.py,sha256=
|
|
9
|
+
arcade_slack/user_retrieval.py,sha256=27PzjG4C_5B17-6hh6BjX7tCNOdAKnJ-tZ8sif6IKnY,6452
|
|
10
|
+
arcade_slack/utils.py,sha256=WQXxUMB75GpYZkqhhXBc3NRZOYFlmGFrSM_aT2EtvUo,25840
|
|
11
11
|
arcade_slack/who_am_i_util.py,sha256=Nf6EdRiURva5jMhVx1lFOoKQ-2SuMwjXYbPCmtj6Zcw,3670
|
|
12
12
|
arcade_slack/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
arcade_slack/tools/chat.py,sha256
|
|
13
|
+
arcade_slack/tools/chat.py,sha256=g7H9aJs8VZod-rMHSaSiAwBUKPY96jvib8DFlmvTTPE,18681
|
|
14
14
|
arcade_slack/tools/system_context.py,sha256=l2gZh_WhrIVL2LzttGAz5yiv0Cl6q_6AFyBBUBskz3E,961
|
|
15
|
-
arcade_slack/tools/users.py,sha256=
|
|
16
|
-
arcade_slack-
|
|
17
|
-
arcade_slack-
|
|
18
|
-
arcade_slack-
|
|
19
|
-
arcade_slack-
|
|
15
|
+
arcade_slack/tools/users.py,sha256=SZAevnpyI9Q-dSFGZCTOL8zwkLRR0iKh0HE3hk54eUY,3642
|
|
16
|
+
arcade_slack-2.1.0.dist-info/METADATA,sha256=lzqZsfeggbNG1lF-CJdX-T7BHXK0-jN2OZXSZFpMi54,1016
|
|
17
|
+
arcade_slack-2.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
18
|
+
arcade_slack-2.1.0.dist-info/licenses/LICENSE,sha256=ixeE7aL9b2B-_ZYHTY1vQcJB4NufKeo-LWwKNObGDN0,1960
|
|
19
|
+
arcade_slack-2.1.0.dist-info/RECORD,,
|
|
File without changes
|