コード例 #1
0
ファイル: notify.py プロジェクト: ofey404/tidb-testing
    failed = 'failed'


def decode(s):
    return b64decode(bytes(s, 'utf-8')).decode('utf-8')


@click.command()
@click.argument('channel')
@click.argument('case')
@click.argument('status')
@click.option('--kv', multiple=True)  # simple kv
@click.option('--b64encodedkvs', default='')  # complex kv
def send_message(channel, case, status, kv, b64encodedkvs):
    status = Status(status)
    client = WebClient(token=os.getenv('SLACK_BOT_TOKEN'))
    fields = []
    fields.append(('status', f'{status.value}'))
    fields.append(('time', f'{datetime.now()}'))

    if status is Status.running:
        color = '#268bd2'  # blue, copied from solorized theme
        title = f"Test case `{case}` {status.value} 🙏"
    else:
        if status is Status.failed:
            color = 'danger'
        else:
            color = 'good'
        title = f"Test case `{case}` {status.value} --- {status.value}"

    if kv:
コード例 #2
0
 def test_default_team_id(self):
     client = WebClient(base_url="http://localhost:8888",
                        team_id="T_DEFAULT")
     resp = client.users_list(token="xoxb-users_list_pagination")
     self.assertIsNone(resp["error"])
コード例 #3
0
ファイル: script.py プロジェクト: harryjjun/slack-sunrise-bot
import schedule
import time
import json
from decouple import config
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

import requests
# from pprint import pprint


TOKEN = config('TOKEN')
channel = '#remote-report'

client = WebClient(token=TOKEN)


def make_quote():
    while True:
        try:
            response = requests.get(
                'https://quote-garden.herokuapp.com/api/v3/quotes/random'
            ).json()
        except json.decoder.JSONDecodeError:
            continue
        else:
            quote_text = response.get('data')[0].get('quoteText')
            quote_author = response.get('data')[0].get('quoteAuthor')
            if response.get('quoteAuthor') == '':
                quote_author = 'Anonymous'
            return f'"{quote_text}"  - {quote_author}'
コード例 #4
0
ファイル: slack_sysinfo.py プロジェクト: agf46/py-api
from slack_sdk.errors import SlackApiError
from slack_print import SlackPrint

host_system = platform.uname()

print(f'{"Analyzing system internals"}')

for i in tqdm(host_system):
    time.sleep(1)

with open("sysinfo.txt", "w") as text_file:
    text_file.write(f"System: {host_system.system}\n")
    text_file.write(f"Node Name: {host_system.node}\n")
    text_file.write(f"Release: {host_system.release}\n")
    text_file.write(f"Version: {host_system.version}\n")
    text_file.write(f"Machine: {host_system.machine}\n")
    text_file.write(f"Processor: {host_system.processor}\n")

# Run SLACK_BOT_TOKEN python3 <script_name.py>
client = WebClient(token=os.environ["SLACK_BOT_TOKEN"])

try:
    filepath = "./sysinfo.txt"
    sp = SlackPrint("SLACK_TOKEN", '#test')  # Enter the slack token here
    sp.upload('sysinfo.txt')
except SlackApiError as e:
    assert e.response["ok"] is False
    assert e.response["error"]
    print(f"got an error: {e.response['error']}")
#Done
コード例 #5
0
    SubsubheaderBlock,
    TextBlock,
)
from notion.client import NotionClient
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

# .envファイルを読み込み、環境変数として扱う
dotenv_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), ".env")
load_dotenv(dotenv_path)
SLACK_TOKEN = os.environ.get("OAuth_Access_Token")
NOTION_TOKEN = os.environ.get("token_v2")
TOP_PAGE_URL = os.environ.get("top_page")

# 各種サービスに接続するインスタンス
slack_client = WebClient(token=SLACK_TOKEN)
notion_client = NotionClient(token_v2=NOTION_TOKEN)

channel = "#bleeeeeefing"

today = datetime.date.today()

# Bleeeeeefingのページを管理しているトップページ
top_page = notion_client.get_block(TOP_PAGE_URL)


def _str_to_date(date: str) -> datetime.date:
    """
    例) "20210214" → datetime.date(2021, 2, 14)
    """
    tdatetime = datetime.datetime.strptime(date, "%Y%m%d")
コード例 #6
0
import os
from slack_sdk import WebClient
from slack_sdk.webhook import WebhookClient
from slack_sdk.errors import SlackApiError

client = WebClient(token=os.environ['SLACK_BOT_TOKEN'])
# Initialize Slack WebHook
webhook = WebhookClient(os.environ['WEBHOOK_URL'])


def SendMessage(message):
    '''Send a simple text message to the #garden channel.'''
    response = webhook.send(text=message)
    assert response.status_code == 200


def UploadFile(filepath, filename):
    '''
    Upload a file on disk (at filepath) to Slack.
    Filename changes the target name in the Slack Channel. Does not relate to the filename on disk.
    '''
    try:
        response = client.files_upload(channels='garden', file=filepath, title=filename)
        assert response["file"]  # the uploaded file
    except SlackApiError as e:
        # You will get a SlackApiError if "ok" is False
        assert e.response["ok"] is False
        assert e.response["error"]  # str like 'invalid_auth', 'channel_not_found'
        print(f"Got an error: {e.response['error']}")
コード例 #7
0
ファイル: authbot.py プロジェクト: hndrewaall/jitsi-party
def sync(
    num_items: int,
    num_pages: int,
    orders_per_page: int,
    request_backoff_seconds: int,
    dry_run: bool,
) -> None:
    """Sync users from Shopify to Cognito"""

    shopify_key = os.environ.get("SHOPIFY_KEY")
    shopify_pass = os.environ.get("SHOPIFY_PASS")
    transport = AIOHTTPTransport(
        url=
        f"https://{shopify_key}:{shopify_pass}@tstvhq.myshopify.com/admin/api/2021-04/graphql.json"
    )
    shopify_client = Client(transport=transport,
                            fetch_schema_from_transport=True)

    aws_client = boto3.client("cognito-idp")
    user_pool_id = os.getenv("AWS_COGNITO_USER_POOL_ID")

    slack_client = WebClient(token=os.environ.get("SLACK_BOT_TOKEN"))

    orders = get_shopify_orders(shopify_client, num_items, num_pages,
                                orders_per_page, request_backoff_seconds)
    current_users = list(get_aws_users(aws_client, user_pool_id))

    new_users: Set[str] = set()
    user_groups: Dict[str, Set[str]] = {}

    for order in orders:
        if len(order.product_handles.intersection(SYNC_MAP.keys())) > 0:
            if order.email is None:
                print("Ignoring order with empty email")

                continue

            if order.email not in current_users:
                new_users.add(order.email.lower())

            if order.email not in user_groups.keys():
                user_groups[order.email] = set()
            groups = user_groups[order.email]

            for handle in order.product_handles:
                if handle in SYNC_MAP.keys():
                    groups.add(SYNC_MAP[handle])

    print(f"Adding {len(new_users)} new users")
    print(f"Adding {len(user_groups.keys())} users to groups")

    if dry_run:
        return

    for user in new_users:
        print(f"Creating user {user}")
        create_aws_user(aws_client, user_pool_id, user)

        sleep(1)

    for user, groups in user_groups.items():
        for group in groups:
            print(f"Adding {user} to {group}")
            add_aws_user_to_group(aws_client, user_pool_id, user, group)

            sleep(1)

    send_slack_message(
        slack_client,
        f"Created {len(new_users)} new users and added {len(user_groups.keys())} users to groups",
    )
コード例 #8
0
def slack_post(channel,
               thread=None,
               text=None,
               content=None,
               username=None,
               icon_url=None,
               attachment=None):
    """
    Post a message on Slack

    The `text` parameter is not required when the `content` parameter is provided, however including it is still
    highly recommended.

    :param channel: The identifier of the Slack conversation to post to
    :param thread: The timestamp of another message to post this message as a reply to
    :param text: Message text (Formatting: https://api.slack.com/reference/surfaces/formatting)
    :param content: List of valid blocks data (https://api.slack.com/block-kit)
    :param username: Name displayed by the bot
    :param icon_url: The URL to an image / icon to display next to the message (profile picture)
    :param attachment: Dictionary with file details - {'name': 'Example File', 'filepath': '/media/slack/example.pdf'}
    :returns: Response object (Dictionary)
    """

    if not settings.SLACK_TOKEN:
        return {'ok': False, 'error': 'config_error'}

    client = WebClient(token=settings.SLACK_TOKEN)

    if attachment:
        filename = attachment['filepath'].split('/')[-1]
        return upload(attachment['filepath'], filename, attachment['name'],
                      text, channel)

    if content:
        try:
            if username:
                response = client.chat_postMessage(channel=channel,
                                                   thread_ts=thread,
                                                   blocks=content,
                                                   text=text,
                                                   username=username,
                                                   icon_url=icon_url)
            else:
                response = client.chat_postMessage(channel=channel,
                                                   thread_ts=thread,
                                                   blocks=content,
                                                   text=text)
            assert response['ok'] is True
            return {'ok': True, 'message': response['message']}
        except SlackApiError as e:
            assert e.response['ok'] is False
            return e.response
    elif text:
        try:
            if username:
                response = client.chat_postMessage(channel=channel,
                                                   thread_ts=thread,
                                                   text=text,
                                                   username=username,
                                                   icon_url=icon_url)
            else:
                response = client.chat_postMessage(channel=channel,
                                                   thread_ts=thread,
                                                   text=text)
            assert response['ok'] is True
            return {'ok': True, 'message': response['message']}
        except SlackApiError as e:
            assert e.response['ok'] is False
            return e.response
    elif not content and not text:
        return {'ok': False, 'error': 'no_text'}
コード例 #9
0
def delete_file(id):
    client = WebClient(token=settings.SLACK_TOKEN)

    response = client.files_delete(file=id)
    return response['ok']
コード例 #10
0
ファイル: skrud_bot.py プロジェクト: skrud/skrud-slack-bot
def _send_slack_message(channel, message_text):
    sc = WebClient(token=BOT_USER_API_KEY)
    sc.chat_postMessage(channel=channel, text=message_text)
コード例 #11
0
ファイル: send_text.py プロジェクト: NightFog007/python_about
import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

import time

client = WebClient(
    token='xoxb-878537608886-1683457705654-Vx4DSD1U2yGuIc2GCxmpVwhI')


def send_message_to_slack(content):

    try:
        response = client.chat_postMessage(channel='梦幻', text=content)
        # assert response["message"]["text"] == "Hello world!"
        # print(response)
    except SlackApiError as e:
        # You will get a SlackApiError if "ok" is False
        assert e.response["ok"] is False
        assert e.response[
            "error"]  # str like 'invalid_auth', 'channel_not_found'
        print(f"Got an error: {e.response['error']}")

    time.sleep(10)


# send_message_to_slack('111233哈哈')
コード例 #12
0
ファイル: slackBot.py プロジェクト: gyusika/slackBot
import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
client = WebClient(
    token='')

# blockchain channel 에서 send message


def sendMessage(message):
    try:
        response = client.chat_postMessage(
            channel='#blockchain', text=message)
        assert response["message"]["text"] == message
    except SlackApiError as e:
        # You will get a SlackApiError if "ok" is False
        assert e.response["ok"] is False
        # str like 'invalid_auth', 'channel_not_found'
        assert e.response["error"]
        print(f"Got an error: {e.response['error']}")


# message 작성
message = "[ENJKRW] UPBIT(500원 100개 매수) BINANCE(400원 100개 매도)"

# sendMessgae 실행
sendMessage(message)
コード例 #13
0
ファイル: trigger_dag.py プロジェクト: dbadanin/airflow_gridU
 def slack_send_message():
     client = WebClient(token=SLACK_TOKEN)
     try:
         response = client.chat_postMessage(channel="airflowtask33", text="Hello from your app! :tada:")
     except SlackApiError as e:
         assert e.response["error"]  # str like 'invalid_auth', 'channel_not_found'
コード例 #14
0
ファイル: main.py プロジェクト: ezawa800/emoji-survey-san
def main() -> None:
    token = input("User OAuth Token: ")
    init_web_client(token)
    # only for post message
    bot_token = input("Bot User OAuth Token: ")
    bot_client = WebClient(token=bot_token)

    public_channel_map = get_public_channel_map()
    if public_channel_map is None:
        sys.exit(1)

    while True:
        ranking_type = input("Choose ranking type [top/unused]: ")
        if ranking_type not in ["top", "unused"]:
            print("Invalid ranking type. Try again.")
            continue
        if ranking_type == "top":
            ranking_limit = input("Choose ranking limit (default: 10): ")
        else:
            ranking_limit = input("Choose ranking limit (default: 0): ")
        if ranking_limit != "" and not ranking_limit.isnumeric():
            print("Invalid ranking limit. Need to input number. Try again.")
            continue
        else:
            default_limit = 10 if ranking_type == "top" else 0
            ranking_limit = int(ranking_limit or default_limit)

        break

    while True:
        if ranking_type == "top":
            target_channel = input(
                "Channel name to survey (default: all channel): "
            )  # noqa: E501
        else:
            confirm_reccomended = input(
                "Surveying all channel is reccomended for unused ranking. Are you sure? [Y/n]: "
            )  # noqa: E501
            if confirm_reccomended == "n":
                target_channel = input(
                    "Channel name to survey (default: all channel): "
                )  # noqa: E501
            else:
                target_channel = ""

        if ranking_type == "top" and target_channel == "":
            confirm = input(
                "It takes long time to survey all channels. Continue? [y/N]: "
            )  # noqa: E501
            if confirm != "y":
                continue
            else:
                print("continue.")
        if target_channel != "" and target_channel not in public_channel_map.keys(
        ):
            print("Error: invalid channel name. Try again.")
            continue
        break

    if ranking_type == "top":
        while True:
            post_channel_name = input("Channel name to post message: ")
            if post_channel_name not in public_channel_map.keys():
                print("Error: invalid channel name. Try again.")
                continue
            break
        while True:
            emoji_type = input(
                "Choose emoji type [custom/all] (default: all): "
            )  # noqa: E501
            if emoji_type not in ["", "custom", "all"]:
                print(
                    "Error: invalid emoji type. Choose [custom/all]. Try again."
                )  # noqa: E501
                continue
            break
    else:
        # Don't post to slack cause unused ranking message is too log to post
        post_channel_name = ""
        # Only custom is available for unused ranking
        emoji_type = "custom"

    print("\nstart surveying...\n")

    if target_channel == "":
        if emoji_type == "custom":
            result = get_custom_emoji_count_in_all_public_channel()
        else:
            result = get_emoji_count_in_all_public_channel()
    else:
        if emoji_type == "custom":
            result = get_custom_emoji_count(target_channel)
        else:
            result = get_emoji_count(target_channel)

    if result is None:
        print("Failed to get count result.")
        sys.exit(1)

    # message header
    message_header = ""
    if ranking_type == "top":
        message_header += f"*Emojiランキング* Top {ranking_limit}\n\n"
    else:
        message_header += f"*使っていないEmojiランキング* Under {ranking_limit}\n\n"
    message_header += "集計範囲: "
    if target_channel == "":
        message_header += "すべてのパブリックチャンネル(log系チャンネルを除く)\n"
    else:
        message_header += f"<#{public_channel_map[target_channel]}>\n"
    message_header += "集計対象: "
    message_header += "カスタムEmojiのみ\n" if emoji_type == "custom" or ranking_type == "unused" else "すべてのEmoji\n"
    message_header += f"集計期間: {OLDEST.strftime(DATE_FORMAT)} ~ {LATEST.strftime(DATE_FORMAT)}\n"
    message_header += "\n"

    # sort and create message
    if ranking_type == "top":
        sorted_result = get_top_emoji_count(result, ranking_limit)
        message = message_header + get_post_message_by_sorted_count(
            sorted_result)
        post_message(bot_client, post_channel_name, message)

        # post deletable message
        # post_message(client, post_channel_name, message)
    else:
        unused_custom_emojis = get_unused_custom_emojis(result, ranking_limit)
        message = message_header + get_post_message_by_unused_custom_emojis(
            unused_custom_emojis)
        # Don't post to slack cause unused ranking has too long message
        print(f"--------\n\n{message}\n\n--------")

    print("\nend surveying.\n")
コード例 #15
0
    def set_token(self):
        if os.path.exists(".env"):
            load_dotenv(verbose=True)

        self.token = os.environ["SLACK_TOKEN"]
        self.client = WebClient(token=self.token)
コード例 #16
0
ファイル: BDminer.py プロジェクト: willhlaw/PAXminer
import sys
import logging
import math

# Configure AWS credentials
config = configparser.ConfigParser()
config.read('../config/credentials.ini')
host = config['aws']['host']
port = int(config['aws']['port'])
user = config['aws']['user']
password = config['aws']['password']
db = sys.argv[1]  # Use this for the multi-region automated update

# Set Slack token
key = sys.argv[2]  # Use this for the multi-region automated update
slack = WebClient(token=key)

#Define AWS Database connection criteria
mydb = pymysql.connect(host=host,
                       port=port,
                       user=user,
                       password=password,
                       db=db,
                       charset='utf8mb4',
                       cursorclass=pymysql.cursors.DictCursor)

# Set epoch and yesterday's timestamp for datetime calculations
epoch = datetime(1970, 1, 1)
yesterday = datetime.now() - timedelta(days=1)
oldest = yesterday.timestamp()
today = datetime.now()
コード例 #17
0
def create_web_client(token: Optional[str] = None) -> WebClient:
    return WebClient(
        token=token,
        user_agent_prefix=f"Bolt/{bolt_version}",
    )
コード例 #18
0
def slack_app():
    if not verify_slack_request(
        signing_secret=signing_secret,
        request_body=request.get_data(),
        timestamp=request.headers.get("X-Slack-Request-Timestamp"),
        signature=request.headers.get("X-Slack-Signature")):
        return make_response("invalid request", 403)

    if "command" in request.form \
        and request.form["command"] == "/do-something":
        trigger_id = request.form["trigger_id"]
        try:
            team_id = request.form["team_id"]
            bot_token = database.find_bot_token(team_id)
            logger.debug(f"token: {bot_token}")
            if not bot_token:
                return make_response("Please install this app first!", 200)

            client = WebClient(token=bot_token)
            response = client.views_open(
                trigger_id=trigger_id,
                view={
                    "type": "modal",
                    "callback_id": "modal-id",
                    "title": {
                        "type": "plain_text",
                        "text": "Awesome Modal"
                    },
                    "submit": {
                        "type": "plain_text",
                        "text": "Submit"
                    },
                    "close": {
                        "type": "plain_text",
                        "text": "Cancel"
                    },
                    "blocks": [
                        {
                            "type": "input",
                            "block_id": "b-id",
                            "label": {
                                "type": "plain_text",
                                "text": "Input label",
                            },
                            "element": {
                                "action_id": "a-id",
                                "type": "plain_text_input",
                            }
                        }
                    ]
                }
            )
            return make_response("", 200)
        except SlackApiError as e:
            code = e.response["error"]
            return make_response(f"Failed to open a modal due to {code}", 200)

    elif "payload" in request.form:
        payload = json.loads(request.form["payload"])
        if payload["type"] == "view_submission" \
            and payload["view"]["callback_id"] == "modal-id":
            submitted_data = payload["view"]["state"]["values"]
            print(submitted_data)  # {'b-id': {'a-id': {'type': 'plain_text_input', 'value': 'your input'}}}
            return make_response("", 200)

    return make_response("", 404)
コード例 #19
0
ファイル: authbot.py プロジェクト: hndrewaall/jitsi-party
def send_message(message: str) -> None:
    """Send a message to Slack"""

    client = WebClient(token=os.environ.get("SLACK_BOT_TOKEN"))
    send_slack_message(client, message)
コード例 #20
0
def slack_api_call(token, method, params):
    client = WebClient(token=token)
    response = client.api_call(api_method=method, params=params)
    print(response)
    return response
コード例 #21
0
class TestViewSubmission:
    signing_secret = "secret"
    valid_token = "xoxb-valid"
    mock_api_server_base_url = "http://localhost:8888"
    signature_verifier = SignatureVerifier(signing_secret)
    web_client = WebClient(
        token=valid_token,
        base_url=mock_api_server_base_url,
    )

    def setup_method(self):
        self.old_os_env = remove_os_env_temporarily()
        setup_mock_web_api_server(self)

    def teardown_method(self):
        cleanup_mock_web_api_server(self)
        restore_os_env(self.old_os_env)

    def generate_signature(self, body: str, timestamp: str):
        return self.signature_verifier.generate_signature(
            body=body,
            timestamp=timestamp,
        )

    def build_headers(self, timestamp: str, body: str):
        return {
            "content-type": ["application/x-www-form-urlencoded"],
            "x-slack-signature": [self.generate_signature(body, timestamp)],
            "x-slack-request-timestamp": [timestamp],
        }

    def build_valid_request(self) -> BoltRequest:
        timestamp = str(int(time()))
        return BoltRequest(
            body=raw_body, headers=self.build_headers(timestamp, raw_body)
        )

    def test_mock_server_is_running(self):
        resp = self.web_client.api_test()
        assert resp != None

    def test_success(self):
        app = App(
            client=self.web_client,
            signing_secret=self.signing_secret,
        )
        app.view("view-id")(simple_listener)

        request = self.build_valid_request()
        response = app.dispatch(request)
        assert response.status == 200
        assert self.mock_received_requests["/auth.test"] == 1

    def test_success_2(self):
        app = App(
            client=self.web_client,
            signing_secret=self.signing_secret,
        )
        app.view_submission("view-id")(simple_listener)

        request = self.build_valid_request()
        response = app.dispatch(request)
        assert response.status == 200
        assert self.mock_received_requests["/auth.test"] == 1

    def test_process_before_response(self):
        app = App(
            client=self.web_client,
            signing_secret=self.signing_secret,
            process_before_response=True,
        )
        app.view("view-id")(simple_listener)

        request = self.build_valid_request()
        response = app.dispatch(request)
        assert response.status == 200
        assert self.mock_received_requests["/auth.test"] == 1

    def test_failure(self):
        app = App(
            client=self.web_client,
            signing_secret=self.signing_secret,
        )
        request = self.build_valid_request()
        response = app.dispatch(request)
        assert response.status == 404
        assert self.mock_received_requests["/auth.test"] == 1

        app.view("view-idddd")(simple_listener)
        response = app.dispatch(request)
        assert response.status == 404
        assert self.mock_received_requests["/auth.test"] == 1

    def test_failure_2(self):
        app = App(
            client=self.web_client,
            signing_secret=self.signing_secret,
        )
        request = self.build_valid_request()
        response = app.dispatch(request)
        assert response.status == 404
        assert self.mock_received_requests["/auth.test"] == 1

        app.view_submission("view-idddd")(simple_listener)
        response = app.dispatch(request)
        assert response.status == 404
        assert self.mock_received_requests["/auth.test"] == 1
コード例 #22
0
from settings import Config, Session
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
from email_validator import validate_email
from twilio.rest import Client
import phonenumbers
from slack_sdk import WebClient
from urllib.request import urlopen

logging.basicConfig()
logging.getLogger('notifications_manager').setLevel(logging.INFO)

email_client = SendGridAPIClient(Config['notifications']['sendgrid_api_key'])
sms_client = Client(Config['notifications']['twilio_sid'],
                    Config['notifications']['twilio_auth_token'])
slack_client = WebClient(token=Config['notifications']['slack_bot_auth_token'])


@validate_arguments(config=dict(arbitrary_types_allowed=True))
def send_notification(recipient: str,
                      message: str,
                      channel: NotificationChannel,
                      scheduled_send_date: datetime = None,
                      subject=None):
    notification = Notification(recipient=recipient,
                                subject=subject,
                                message=message,
                                channel=channel,
                                scheduled_send_date=scheduled_send_date)

    db = Session()
コード例 #23
0
    def display_karma_leaderboards(self) -> Tuple[str, str, str]:
        """Prints rudimentary user and thing leaderboards.

        Returns:
        A message, if applicable, a string representation of the user leaderboard, and a
        string representation of the thing leaderboard.
        """
        Row = namedtuple("Row", "name pluses minuses net_score")
        try:
            with open(self.karma_file_path, "r",
                      encoding="utf-8") as karma_file:
                cur_karma = json.load(karma_file)

            user_table = []
            thing_table = []
            for item in cur_karma:
                name = item["name"]
                pluses = item["pluses"]
                minuses = item["minuses"]
                delta = pluses - minuses

                if name.startswith("<@"):
                    name = name.lstrip("<@").rstrip(">")
                    user_table.append(Row(name, pluses, minuses, delta))
                elif name.startswith(
                        "<!"):  # Special case for @everyone, @channel, @here
                    name = name.lstrip("<!").rstrip(">")
                    user_table.append(Row(name, pluses, minuses, delta))
                else:
                    thing_table.append(Row(name, pluses, minuses, delta))
            assert user_table or thing_table
        except (ValueError, AssertionError):  # Empty file or no file present
            self.logger.exception(
                "Empty karma file or no file present, return.")
            return ("No karma yet!", "", "")
        try:
            web_client = WebClient(token=os.environ.get("SLACK_BOT_TOKEN"))
            request = web_client.users_list()
            ids_to_names = {}
            if request["ok"]:
                for member in request["members"]:
                    try:
                        name = member.get("real_name") or member.get("name")
                        assert name
                        ids_to_names[member["id"]] = name
                    except AssertionError:
                        self.logger.debug("Unable to get name for id %s",
                                          member["id"])

            # Convert user IDs to actual names
            usr_table = []
            for row in user_table:
                if row.name in ids_to_names:
                    name = ids_to_names[row.name]
                    usr_table.append(
                        Row(name, row.pluses, row.minuses, row.net_score))
                else:
                    usr_table.append(row)

            usr_table = sorted(usr_table,
                               reverse=True,
                               key=lambda x: x.net_score)[:10]
            thing_table = sorted(thing_table,
                                 reverse=True,
                                 key=lambda x: x.net_score)[:10]

            headers = ["Name", "Pluses", "Minuses", "Net Score"]
            users = tabulate([list(row) for row in usr_table],
                             headers,
                             tablefmt="github")
            things = tabulate([list(row) for row in thing_table],
                              headers,
                              tablefmt="github")

            return (
                "",
                f"User leaderboard:\n ```{users}```",
                f"Thing leaderboard:\n ```{things}```",
            )

        except SlackApiError as api_err:
            self.logger.error("Failed to generate leaderboard due to %s",
                              api_err)
            return ("", "", "")
コード例 #24
0
class TestErrorHandler:
    signing_secret = "secret"
    valid_token = "xoxb-valid"
    mock_api_server_base_url = "http://localhost:8888"
    signature_verifier = SignatureVerifier(signing_secret)
    web_client = WebClient(
        token=valid_token,
        base_url=mock_api_server_base_url,
    )

    def setup_method(self):
        self.old_os_env = remove_os_env_temporarily()
        setup_mock_web_api_server(self)

    def teardown_method(self):
        cleanup_mock_web_api_server(self)
        restore_os_env(self.old_os_env)

    # ----------------
    #  utilities
    # ----------------

    def generate_signature(self, body: str, timestamp: str):
        return self.signature_verifier.generate_signature(
            body=body,
            timestamp=timestamp,
        )

    def build_headers(self, timestamp: str, body: str):
        return {
            "content-type": ["application/x-www-form-urlencoded"],
            "x-slack-signature": [self.generate_signature(body, timestamp)],
            "x-slack-request-timestamp": [timestamp],
        }

    def build_valid_request(self) -> BoltRequest:
        body = {
            "type": "block_actions",
            "user": {
                "id": "W111",
            },
            "api_app_id": "A111",
            "token": "verification_token",
            "trigger_id": "111.222.valid",
            "team": {
                "id": "T111",
            },
            "channel": {"id": "C111", "name": "test-channel"},
            "response_url": "https://hooks.slack.com/actions/T111/111/random-value",
            "actions": [
                {
                    "action_id": "a",
                    "block_id": "b",
                    "text": {"type": "plain_text", "text": "Button"},
                    "value": "click_me_123",
                    "type": "button",
                    "action_ts": "1596530385.194939",
                }
            ],
        }
        raw_body = f"payload={quote(json.dumps(body))}"
        timestamp = str(int(time.time()))
        return BoltRequest(
            body=raw_body, headers=self.build_headers(timestamp, raw_body)
        )

    # ----------------
    #  tests
    # ----------------

    def test_lazy(self):
        def just_ack(ack):
            ack()

        def async1(say):
            time.sleep(0.3)
            say(text="lazy function 1")

        def async2(say):
            time.sleep(0.5)
            say(text="lazy function 2")

        app = App(
            client=self.web_client,
            signing_secret=self.signing_secret,
        )
        app.action("a")(
            ack=just_ack,
            lazy=[async1, async2],
        )

        request = self.build_valid_request()
        response = app.dispatch(request)
        assert response.status == 200
        time.sleep(1)  # wait a bit
        assert self.mock_received_requests["/chat.postMessage"] == 2

    def test_lazy_class(self):
        def just_ack(ack):
            ack()

        class LazyClass:
            def __call__(self, say):
                time.sleep(0.3)
                say(text="lazy function 1")

        def async2(say):
            time.sleep(0.5)
            say(text="lazy function 2")

        app = App(
            client=self.web_client,
            signing_secret=self.signing_secret,
        )
        app.action("a")(
            ack=just_ack,
            lazy=[LazyClass(), async2],
        )

        request = self.build_valid_request()
        response = app.dispatch(request)
        assert response.status == 200
        time.sleep(1)  # wait a bit
        assert self.mock_received_requests["/chat.postMessage"] == 2
コード例 #25
0
 def test_timeout_issue_712(self):
     client = WebClient(base_url="http://localhost:8888", timeout=1)
     with self.assertRaises(socket.timeout):
         client.users_list(token="xoxb-timeout")
コード例 #26
0
def post_slack(text, param):
    client = WebClient(token=SLACK_TOKEN)
    response = client.chat_postMessage(channel=SLACK_CHANNEL,
                                       text=text,
                                       thread_ts=param['ts'])
コード例 #27
0
 def __init__(self, token):
     self.client = WebClient(token=token)
コード例 #28
0
    # Post updates to #envoy-maintainer-oncall
    unassigned_prs = maintainers_and_messages['unassigned']
    if unassigned_prs:
        try:
            response = client.chat_postMessage(
                channel='#envoy-maintainer-oncall',
                text=(
                    "*'Unassigned' PRs* (PRs with no maintainer assigned)\n%s"
                    % unassigned_prs))
            response = client.chat_postMessage(
                channel='#envoy-maintainer-oncall',
                text=("*Stalled PRs*\n\n%s" % out_slo_prs))
        except SlackApiError as e:
            print("Unexpected error %s", e.response["error"])


if __name__ == '__main__':
    maintainers_and_messages, shephards_and_messages, stalled_prs = track_prs()

    SLACK_BOT_TOKEN = os.getenv('SLACK_BOT_TOKEN')
    if not SLACK_BOT_TOKEN:
        print(
            'Missing SLACK_BOT_TOKEN: please export token from https://api.slack.com/apps/A023NPQQ33K/oauth?'
        )
        sys.exit(1)

    client = WebClient(token=SLACK_BOT_TOKEN)
    post_to_oncall(client, maintainers_and_messages['unassigned'], stalled_prs)
    post_to_assignee(client, shephards_and_messages, API_REVIEWERS)
    post_to_assignee(client, maintainers_and_messages, MAINTAINERS)
コード例 #29
0
 def setUp(self):
     setup_mock_web_api_server(self)
     self.web_client = WebClient(
         token="xoxb-api_test",
         base_url="http://localhost:8888",
     )
コード例 #30
0
ファイル: sensors.py プロジェクト: trevenrawr/dagster
def make_slack_on_pipeline_failure_sensor(
    channel: str,
    slack_token: str,
    text_fn: Callable[[PipelineFailureSensorContext],
                      str] = _default_failure_message_text_fn,
    blocks_fn: Optional[Callable[[PipelineFailureSensorContext],
                                 List[Dict]]] = None,
    pipeline_selection: Optional[List[str]] = None,
    name: Optional[str] = None,
    dagit_base_url: Optional[str] = None,
    default_status: DefaultSensorStatus = DefaultSensorStatus.STOPPED,
):
    """Create a sensor on pipeline failures that will message the given Slack channel.

    Args:
        channel (str): The channel to send the message to (e.g. "#my_channel")
        slack_token (str): The slack token.
            Tokens are typically either user tokens or bot tokens. More in the Slack API
            documentation here: https://api.slack.com/docs/token-types
        text_fn (Optional(Callable[[PipelineFailureSensorContext], str])): Function which
            takes in the ``PipelineFailureSensorContext`` and outputs the message you want to send.
            Defaults to a text message that contains error message, pipeline name, and run ID.
            The usage of the `text_fn` changes depending on whether you're using `blocks_fn`. If you
            are using `blocks_fn`, this is used as a fallback string to display in notifications. If
            you aren't, this is the main body text of the message. It can be formatted as plain text,
            or with mrkdwn.
            See more details in https://api.slack.com/methods/chat.postMessage#text_usage
        blocks_fn (Callable[[PipelineFailureSensorContext], List[Dict]]): Function which takes in
            the ``PipelineFailureSensorContext`` and outputs the message blocks you want to send.
            See information about Blocks in https://api.slack.com/reference/block-kit/blocks
        pipeline_selection (Optional[List[str]]): Names of the pipelines that will be monitored by
            this failure sensor. Defaults to None, which means the alert will be sent when any
            pipeline in the repository fails.
        name: (Optional[str]): The name of the sensor. Defaults to "slack_on_pipeline_failure".
        dagit_base_url: (Optional[str]): The base url of your Dagit instance. Specify this to allow
            messages to include deeplinks to the failed pipeline run.
        default_status (DefaultSensorStatus): Whether the sensor starts as running or not. The default
            status can be overridden from Dagit or via the GraphQL API.

    Examples:

        .. code-block:: python

            slack_on_pipeline_failure = make_slack_on_pipeline_failure_sensor(
                "#my_channel",
                os.getenv("MY_SLACK_TOKEN")
            )

            @repository
            def my_repo():
                return [my_pipeline + slack_on_pipeline_failure]

        .. code-block:: python

            def my_message_fn(context: PipelineFailureSensorContext) -> str:
                return "Pipeline {pipeline_name} failed! Error: {error}".format(
                    pipeline_name=context.pipeline_run.pipeline_name,
                    error=context.failure_event.message,
                )

            slack_on_pipeline_failure = make_slack_on_pipeline_failure_sensor(
                channel="#my_channel",
                slack_token=os.getenv("MY_SLACK_TOKEN"),
                message_fn=my_message_fn,
                dagit_base_url="http://mycoolsite.com",
            )


    """

    slack_client = WebClient(token=slack_token)

    @pipeline_failure_sensor(name=name,
                             pipeline_selection=pipeline_selection,
                             default_status=default_status)
    def slack_on_pipeline_failure(context: PipelineFailureSensorContext):

        blocks, main_body_text = _build_slack_blocks_and_text(
            context=context,
            text_fn=text_fn,
            blocks_fn=blocks_fn,
            dagit_base_url=dagit_base_url)

        slack_client.chat_postMessage(channel=channel,
                                      blocks=blocks,
                                      text=main_body_text)

    return slack_on_pipeline_failure