async def make_snippet(action, app): if not action["message"]["text"].startswith("```"): response = Message() response["channel"] = action["channel"]["id"] response["text"] = f"""```{action["message"]["text"]}```""" tip_message = Message() tip_message["channel"] = action["channel"]["id"] tip_message["user"] = action["message"]["user"] tip_message["text"] = ( "Please use the snippet feature, or backticks, when sharing code. You can do so by " "clicking on the :heavy_plus_sign: on the left of the input box for a snippet.\n" "For more information on snippets click " "<https://get.slack.help/hc/en-us/articles/204145658-Create-a-snippet|here>.\n" "For more information on inline code formatting with backticks click " "<https://get.slack.help/hc/en-us/articles/202288908-Format-your-messages#inline-code|here>." ) await asyncio.gather( app.plugins["slack"].api.query(url=methods.CHAT_POST_EPHEMERAL, data=tip_message), app.plugins["slack"].api.query(url=methods.CHAT_POST_MESSAGE, data=response), ) else: response = Message() response["text"] = "Sorry I'm unable to format that message" await app.plugins["slack"].api.query(url=action["response_url"], data=response)
def build_messages( user_id) -> Tuple[Message, Message, Message, Message, Message]: initial_message = base_user_message(user_id) initial_message["text"] = team_join_initial_message(user_id) second_message = base_user_message(user_id) second_message["text"] = second_team_join_message() second_message["attachments"] = external_button_attachments() action_menu = base_user_message(user_id) action_menu["text"] = "We recommend the following resources." action_menu["attachments"] = base_resources() community_message = Message() community_message["text"] = f":tada: <@{user_id}> has joined! :tada:" community_message["attachments"] = not_greeted_attachment() community_message["channel"] = COMMUNITY_CHANNEL outreach_team_message = Message() outreach_team_message["text"] = ( f":spiral_note_pad: Outreach Team: Please reach out to <@{user_id}> via DM" f":spiral_note_pad: ") outreach_team_message["attachments"] = not_direct_messaged_attachment() outreach_team_message["channel"] = COMMUNITY_CHANNEL return ( initial_message, second_message, action_menu, community_message, outreach_team_message, )
async def report(action, app): admin_msg = Message() admin_msg["channel"] = ADMIN_CHANNEL admin_msg["attachments"] = [{ "fallback": f'Report from {action["user"]["name"]}', "title": f'Report from <@{action["user"]["id"]}>', "color": "danger", "fields": [{ "title": "User", "value": f'<@{action["submission"]["user"]}>', "short": True, }], }] if action["submission"]["channel"]: admin_msg["attachments"][0]["fields"].append({ "title": "Channel", "value": f'<#{action["submission"]["channel"]}>', "short": True, }) admin_msg["attachments"][0]["fields"].append({ "title": "Comment", "value": action["submission"]["comment"], "short": False }) await app.plugins["slack"].api.query(url=methods.CHAT_POST_MESSAGE, data=admin_msg) async with app["plugins"]["pg"].connection() as pg_con: await pg_con.execute( """INSERT INTO slack.reports ("user", channel, comment, by) VALUES ($1, $2, $3, $4)""", action["submission"]["user"], action["submission"]["channel"], action["submission"]["comment"], action["user"]["id"], ) response = Message() response["response_type"] = "ephemeral" response[ "text"] = "Thank you for your report. An admin will look into it soon." await app.plugins["slack"].api.query(url=action["response_url"], data=response)
async def _pr_message(event, app, color="good", action=None): msg = Message() msg["channel"] = CHANNEL msg["attachments"] = [{ "fallback": "pull request {}".format(event.data["action"]), "color": color, "text": "*<{url}|{title}>*\n{body}".format( url=event.data["pull_request"]["html_url"], title=event.data["pull_request"]["title"], body=event.data["pull_request"]["body"], ), "title": "Pull request {action} in <{repo_url}|{name}>".format( repo_url=event.data["repository"]["html_url"], name=event.data["repository"]["name"], action=action or event.data["action"], ), "author_icon": event.data["sender"]["avatar_url"], "author_name": event.data["sender"]["login"], "author_link": event.data["sender"]["html_url"], "footer": "+ {add} / - {del_}".format( add=event.data["pull_request"]["additions"], del_=event.data["pull_request"]["deletions"], ), "mrkdwn_in": ["text"], }] await app.plugins["slack"].api.query(methods.CHAT_POST_MESSAGE, data=msg)
async def _issues_message(event, app, color="good"): msg = Message() msg["channel"] = CHANNEL msg["attachments"] = [{ "fallback": "issue {}".format(event.data["action"]), "color": color, "text": "*<{url}|{title}>*\n{body}".format( url=event.data["issue"]["html_url"], title=event.data["issue"]["title"], body=event.data["issue"]["body"], ), "title": "Issue {action} in <{repo_url}|{name}>".format( repo_url=event.data["repository"]["html_url"], name=event.data["repository"]["name"], action=event.data["action"], ), "author_icon": event.data["sender"]["avatar_url"], "author_name": event.data["sender"]["login"], "author_link": event.data["sender"]["html_url"], "footer": ", ".join(label["name"] for label in event.data["issue"]["labels"]), "mrkdwn_in": ["text"], }] await app.plugins["slack"].api.query(methods.CHAT_POST_MESSAGE, data=msg)
async def resources(command, app): """ Share resources for new developers getting started with python """ slack = app.plugins["slack"] response = Message() response["channel"] = command["channel_id"] response["unfurl_links"] = False response["text"] = ( "Listed below are some great resources to get started on learning python:\n" "*Books:*\n" "* <https://www.amazon.com/Learning-Python-Powerful-Object-Oriented-Programming-ebook/dp/B00DDZPC9S/|Learning Python: Powerful Object Oriented Programming>\n" "* <https://www.amazon.com/Automate-Boring-Stuff-Python-Programming-ebook/dp/B00WJ049VU/|Automate the Boring Stuff>\n" "* <https://www.amazon.com/Hitchhikers-Guide-Python-Practices-Development-ebook/dp/B01L9W8CVG/|The Hitchhiker's Guide to Python: Best Practices for Development>\n" "* <https://www.amazon.com/Think-Python-Like-Computer-Scientist-ebook/dp/B018UXJ9EQ/|Think Python: How to Think Like a Computer Scientist>\n" "* <https://runestone.academy/runestone/books/published/thinkcspy/index.html|How to Think Like a Computer Scientist: Interactive Edition>\n" "* <http://www.obeythetestinggoat.com/book/praise.harry.html|Test Driven Development with Python aka 'Obey the Testing Goat'>\n" "* <https://github.com/EbookFoundation/free-programming-books/blob/master/free-programming-books.md#python|List of free Python e-books>\n" "*Videos:*\n" "* <https://www.youtube.com/channel/UCI0vQvr9aFn27yR6Ej6n5Uz|Dan Bader's Python Tutorials>\n" "* <https://pyvideo.org/|PyVideo.org>\n" "* <https://www.youtube.com/watch?v=bgBWp9EIlMM|Engineer Man>\n" "*Online Courses:*\n" "* <https://www.datacamp.com/|DataCamp Data Science and Machine Learning>\n" "*Cheat Sheets:*\n" "* <https://www.pythoncheatsheet.org/|Online Python Cheat Sheet>\n" "*Project Based Learning:*\n" "* <https://github.com/tuvtran/project-based-learning|Project Based Learning Courses>\n\n" "For the full list of resources see our curated list <https://github.com/pyslackers/learning-resources|here>\n" ) await app.plugins["slack"].api.query(url=methods.CHAT_POST_MESSAGE, data=response)
async def etc_finance_bell(bot, state): LOG.info("Posting %s bell to #etc_finance", state) holidays = [ datetime.date(2018, 1, 1), datetime.date(2018, 1, 15), datetime.date(2018, 2, 19), datetime.date(2018, 3, 30), datetime.date(2018, 5, 28), datetime.date(2018, 7, 4), datetime.date(2018, 9, 3), datetime.date(2018, 11, 22), datetime.date(2018, 12, 25), ] message = Message() message["channel"] = "etc_finance" if datetime.date.today() in holidays: message[ "text"] = """:bell: :bell: :bell: The US Stock Market is *CLOSED for holiday*. :bell: :bell: :bell:""" state = "holiday" elif state == "open": message[ "text"] = """:bell: :bell: :bell: The US Stock Market is now *OPEN* for trading. :bell: :bell: :bell:""" elif state == "closed": message[ "text"] = """:bell: :bell: :bell: The US Stock Market is now *CLOSED* for trading. :bell: :bell: :bell:""" await bot["plugins"]["slack"].api.query(url=methods.CHAT_POST_MESSAGE, data=message)
async def advent_of_code(bot): LOG.info("Creating Advent Of Code threads...") for_day = datetime.datetime.now(tz=pytz.timezone("America/New_York")) year, day = for_day.year, for_day.day for part in range(1, 3): message = Message() message["channel"] = "advent_of_code" message["attachments"] = [{ "fallback": "Official {} Advent Of Code Thread for Day {} Part {}".format( year, day, part), "color": ["#ff0000", "#378b29"][ # red # green (part - 1) // 1], # red=part 1, green=part 2 "title": ":christmas_tree: {} Advent of Code Thread: Day {} Part {} :christmas_tree:" .format(year, day, part), "title_link": "https://adventofcode.com/{}/day/{}".format(year, day), "text": ("Post solutions to part {} in this thread, in any language, to avoid spoilers!" .format(part)), "footer": "Advent of Code", "footer_icon": "https://adventofcode.com/favicon.ico", "ts": int(for_day.timestamp()), }] await bot["plugins"]["slack"].api.query(url=methods.CHAT_POST_MESSAGE, data=message)
async def repo_deleted(event, app): msg = Message() msg["channel"] = CHANNEL msg["text"] = "Repository {repo} deleted by {user} :cold_sweat:".format( repo=event.data["repository"]["name"], user=event.data["sender"]["login"]) await app.plugins["slack"].api.query(methods.CHAT_POST_MESSAGE, data=msg)
async def pin_added_revert(action, app): response = Message() response["channel"] = action["channel"]["id"] response["ts"] = action["message_ts"] response["attachments"] = action["original_message"]["attachments"] response["attachments"][0]["color"] = "danger" response["attachments"][0][ "pretext"] = f'Pin reverted by <@{action["user"]["id"]}>' del response["attachments"][0]["actions"] action_data = json.loads(action["actions"][0]["value"]) remove_data = {"channel": action_data["channel"]} if action_data["item_type"] == "message": remove_data["timestamp"] = action_data["item_id"] elif action_data["item_type"] == "file": remove_data["file"] = action_data["item_id"] elif action_data["item_type"] == "file_comment": remove_data["file_comment"] = action_data["item_id"] else: raise TypeError(f'Unknown pin type: {action_data["type"]}') try: await app.plugins["slack"].api.query(url=methods.PINS_REMOVE, data=remove_data) except SlackAPIError as e: if e.error != "no_pin": raise await app.plugins["slack"].api.query(url=action["response_url"], data=response)
async def snippet(command, app): """Post a message to the current channel about using snippets and backticks to visually format code.""" response = Message() response["channel"] = command["channel_id"] response["unfurl_links"] = False response["text"] = ( "Please use the snippet feature, or backticks, when sharing code. \n" "To include a snippet, click the :paperclip: on the left and hover over " "`Create new...` then select `Code or text snippet`.\n" "By wrapping the text/code with backticks (`) you get:\n" "`text formatted like this`\n" "By wrapping a multiple line block with three backticks (```) you can get:\n" ) await app.plugins["slack"].api.query(url=methods.CHAT_POST_MESSAGE, data=response) response["text"] = ( "```\n" "A multiline codeblock\nwhich is great for short snippets!\n" "```\n" "For more information on snippets, click " "<https://get.slack.help/hc/en-us/articles/204145658-Create-a-snippet|here>.\n" "For more information on inline code formatting with backticks click " "<https://get.slack.help/hc/en-us/articles/202288908-Format-your-messages#inline-code|here>." ) await app.plugins["slack"].api.query(url=methods.CHAT_POST_MESSAGE, data=response)
def base_greeted_response(action): response = Message() response['text'] = action['original_message']['text'] response['channel'] = action['channel']['id'] response['ts'] = action['message_ts'] return response
async def post(self): payload = await self.request.json() logger.debug("Incoming readthedocs notification: %s", payload) project = payload.get("name") if not project: return web.Response(status=400) build = payload.get("build") if not build: return web.Response(status=400) if build.get("state") != "finished": return web.Response(status=200) commit = build["commit"][:7] if build["success"]: status, emoji = "successful", "toot" else: status, emoji = "failed", "cry" msg = Message() msg["channel"] = settings.READTHEDOCS_NOTIFICATION_CHANNEL msg["text"] = f"""Building of {project}@{commit} documentation {status} ! :{emoji}:""" await self.request.app["slack_client"].query(methods.CHAT_POST_MESSAGE, data=msg) return web.Response(status=200)
async def post_slack_codewars_challenge( slack_client: SlackAPI, pg: asyncpg.pool.Pool, ) -> None: async with pg.acquire() as conn: challenge = await database.get_challenge(conn) message = Message() message["channel"] = "CEFJ9TJNL" # advent_of_code if challenge: message["attachments"] = [ { "fallback": f"Codewars challenge: https://www.codewars.com/kata/{challenge}", "color": "#ff0000", "title": "Weekly Codewars challenge", "title_link": f"https://www.codewars.com/kata/{challenge}", "text": "Discuss in this thread", "footer": "Codewars", "footer_icon": "https://codewars.com/favicon.ico", } ] else: message["attachments"] = [ { "fallback": "Codewars challenge: no challenge found", "color": "#ff0000", "title": "Weekly Codewars challenge", "title_link": "https://www.codewars.com", "text": "No challenge found :sad-panda:, please seed new challenges ", "footer": "Codewars", "footer_icon": "https://codewars.com/favicon.ico", } ] await slack_client.query(slack.methods.CHAT_POST_MESSAGE, data=message)
async def gif_search_cancel(action, app): response = Message() response["channel"] = action["channel"]["id"] response["ts"] = action["message_ts"] response["text"] = "Cancelled" await app.plugins["slack"].api.query(url=action["response_url"], data=response)
async def recording_emoji(action, app): recording_id = int(action["actions"][0]["value"]) async with app["plugins"]["pg"].connection() as pg_con: created = await pg_con.fetchval( """UPDATE slack.recordings SET commit = TRUE WHERE id = $1 AND "end" is NOT NULL RETURNING id""", recording_id, ) response = Message() response["channel"] = action["channel"]["id"] response["ts"] = action["message_ts"] if created: response["text"] = "Conversation successfully recorded." else: async with app["plugins"]["pg"].connection() as pg_con: exist = await pg_con.fetchval( """SELECT id FROM slack.recordings WHERE id = $1""", recording_id) if not exist: response["text"] = "Conversation not recorded. Please try again." else: response["text"] = ( """*Could not find message with :stop_recording:*. \n\n""" """Would you like to record this conversation ?""") response["attachments"] = [{ "fallback": "start recording", "callback_id": "recording", "actions": [ { "name": "message", "text": "Yes, Until this message", "style": "primary", "type": "button", "value": recording_id, }, { "name": "emoji", "text": "Yes, Until the :stop_recording: emoji", "style": "primary", "type": "button", "value": recording_id, }, { "name": "cancel", "text": "Cancel", "style": "danger", "type": "button", "value": recording_id, }, ], }] await app.plugins["slack"].api.query(url=action["response_url"], data=response)
async def release_created(event, app): msg = Message() msg["channel"] = CHANNEL msg["text"] = "Release {release} created in {repo} by {user}".format( release=event.data["release"]["tag_name"], repo=event.data["repository"]["name"], user=event.data["sender"]["login"], ) await app.plugins["slack"].api.query(methods.CHAT_POST_MESSAGE, data=msg)
def _gif_search_next_previous(action, index): response = Message() response["channel"] = action["channel"]["id"] response["ts"] = action["message_ts"] data = json.loads(action["actions"][0]["value"]) data["index"] += index url = data["urls"][data["index"]] data_json = json.dumps(data) response["attachments"] = [{ "title": f'<@{action["user"]["id"]}> Searched giphy for: `{data["search"]}`', "fallback": f'<@{action["user"]["id"]}> Searched giphy for: `{data["search"]}`', "image_url": url, "callback_id": "gif_search", "actions": [ { "name": "ok", "text": "Send", "style": "primary", "value": data_json, "type": "button", }, { "name": "cancel", "text": "Cancel", "style": "danger", "value": data_json, "type": "button", }, ], }] if len(data["urls"]) > data["index"] + 1: response["attachments"][0]["actions"].insert(1, { "name": "next", "text": "Next", "value": data_json, "type": "button" }) if data["index"] != 0: response["attachments"][0]["actions"].insert( 1, { "name": "previous", "text": "Previous", "value": data_json, "type": "button", }, ) return response
def _create_messages(mentors: List[str], request: dict, requested_mentor_message: str, service_translation: str, slack_id: str) -> Tuple[Message, Message, Message]: first_message = Message() first_message['text'] = mentor_request_text(slack_id, service_translation, request.get('skillsets', None), requested_mentor_message) first_message['attachments'] = claim_mentee_attachment(request['record']) first_message['channel'] = MENTORS_CHANNEL details_message = Message() details_message[ 'text'] = f"Additional details: {request.get('details', 'None Given')}" details_message['channel'] = MENTORS_CHANNEL matching_mentors_message = Message() matching_mentors_message[ 'text'] = "Mentors matching all or some of the requested skillsets: " + ' '.join( mentors) matching_mentors_message['channel'] = MENTORS_CHANNEL return first_message, details_message, matching_mentors_message
async def sirbot_help(command, app): slack = app.plugins["slack"] response = Message() response["channel"] = command["channel_id"] response["unfurl_links"] = False response["text"] = "Community Slack Commands" response["attachments"] = [{"color": "good", "fields": HELP_FIELD_DESCRIPTIONS}] await slack.api.query(url=methods.CHAT_POST_MESSAGE, data=response)
async def snippet(command, app): response = Message() response["channel"] = command["channel_id"] response["unfurl_links"] = False response[ "text" ] = "Please use the snippet feature, or backticks, when sharing code. You can do so by " "clicking on the :heavy_plus_sign: on the left of the input box for a snippet.\n" "For more information on snippets click " "<https://get.slack.help/hc/en-us/articles/204145658-Create-a-snippet|here>.\n" "For more information on inline code formatting with backticks click " "<https://get.slack.help/hc/en-us/articles/202288908-Format-your-messages#inline-code|here>." await app.plugins["slack"].api.query(url=methods.CHAT_POST_MESSAGE, data=response)
async def tell_admin(action, app): admin_msg = Message() admin_msg["channel"] = ADMIN_CHANNEL admin_msg["attachments"] = [{ "fallback": f'Message from {action["user"]["name"]}', "title": f'Message from <@{action["user"]["id"]}>', "color": "good", "text": action["submission"]["message"], }] await app.plugins["slack"].api.query(url=methods.CHAT_POST_MESSAGE, data=admin_msg) response = Message() response["response_type"] = "ephemeral" response["text"] = "Thank you for your message." await app.plugins["slack"].api.query(url=action["response_url"], data=response)
async def here_bad(event: Message, app: SirBot) -> None: if "channel_type" in event and event["channel_type"] != "im": user = event.get("user") user_id = f"<@{user}>" if user else "Hey you" await app.plugins["slack"].api.query( methods.CHAT_POST_MESSAGE, data=dict( channel=event["channel"], text=f"{user_id} - this had better be important!", ), )
async def sponsors(command, app): slack = app.plugins["slack"] response = Message() response["channel"] = command["channel_id"] response["unfurl_links"] = False response[ "text" ] = "Thanks to our sponsors, <https://digitalocean.com|Digital Ocean> and " "<https://sentry.io|Sentry> for providing hosting & services helping us " "host our <https://www.pyslackers.com|website> and Sir Bot-a-lot.\n" "If you are planning on using one of those services please use our referral codes: \n" "1. <https://m.do.co/c/457f0988c477|Digital Ocean referral code>\n" "2. <https://sentry.io/?utm_source=referral&utm_content=pyslackers&utm_campaign=community|" "Sentry referral code>." await slack.api.query(url=methods.CHAT_POST_MESSAGE, data=response)
async def tech_tips(event: Message, app: SirBot): if not_bot_message(event): logger.info( f'tech logging: {event}') try: tech_terms: dict = await TechTerms(event['channel'], event['user'], event.get('text'), app).grab_values() await app.plugins["slack"].api.query(methods.CHAT_POST_MESSAGE, tech_terms['message']) except Exception as E: logger.exception(E)
async def tech_tips(event: Message, app: SirBot): if not_bot_message(event): logger.info(f"tech tips logging: {event}") try: tech_terms = await TechTerms(event["channel"], event["user"], event.get("text"), app).grab_values() await app.plugins["slack"].api.query(methods.CHAT_POST_MESSAGE, tech_terms["message"]) except Exception: logger.debug( f"Exception thrown while logging message_changed {event}")
async def pin_added_validate(action, app): response = Message() response["channel"] = action["channel"]["id"] response["ts"] = action["message_ts"] response["attachments"] = action["original_message"]["attachments"] response["attachments"][0]["color"] = "good" response["attachments"][0][ "pretext"] = f'Pin validated by <@{action["user"]["id"]}>' del response["attachments"][0]["actions"] await app.plugins["slack"].api.query(url=action["response_url"], data=response)
async def user_cleanup_cancel(action, app): response = Message() response["channel"] = action["channel"]["id"] response["ts"] = action["message_ts"] response["attachments"] = action["original_message"]["attachments"] response["attachments"][0]["color"] = "good" response["attachments"][0][ "text"] = f'Cancelled by <@{action["user"]["id"]}>' del response["attachments"][0]["actions"] await app.plugins["slack"].api.query(url=action["response_url"], data=response)
async def channel_topic(message, app): if ( message["user"] not in app["plugins"]["slack"].admins and message["user"] != app["plugins"]["slack"].bot_user_id ): async with app["plugins"]["pg"].connection() as pg_con: channel = await pg_con.fetchrow( """SELECT raw FROM slack.channels WHERE id = $1""", message["channel"] ) LOG.debug(channel) if channel: old_topic = channel["raw"]["topic"]["value"] else: old_topic = "Original topic not found" response = Message() response["channel"] = ADMIN_CHANNEL response["attachments"] = [ { "fallback": "Channel topic changed notice: old topic", "title": f'<@{message["user"]}> changed <#{message["channel"]}> topic.', "fields": [ {"title": "Previous topic", "value": old_topic}, {"title": "New topic", "value": message["topic"]}, ], } ] if channel: response["attachments"][0]["callback_id"] = "topic_change" response["attachments"][0]["actions"] = [ { "name": "validate", "text": "Validate", "style": "primary", "type": "button", }, { "name": "revert", "text": "Revert", "style": "danger", "value": json.dumps( {"channel": message["channel"], "old_topic": old_topic} ), "type": "button", }, ] await app["plugins"]["slack"].api.query( url=methods.CHAT_POST_MESSAGE, data=response )
async def just_ask(command, app): slack = app.plugins["slack"] response = Message() response["channel"] = command["channel_id"] response["unfurl_links"] = False response["text"] = ( "If you have a question, please just ask it. Please do not ask for topic experts; " "do not DM or ping random users. We cannot begin to answer a question until we actually get a question. \n\n" "<http://sol.gfxile.net/dontask.html|*Asking Questions*>") await slack.api.query(url=methods.CHAT_POST_MESSAGE, data=response)