{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Introduction: Interacting with Slack from Python\n",
    "\n",
    "In this notebook, we will use `Slacker` to interact with Slack. This allows us to send messages and upload files, which can be useful when training models, or monitoring scripts (or just for fun of course)!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "distributed 1.20.2 has requirement tornado>=4.5.1, but you'll have tornado 4.3 which is incompatible.\n",
      "You are using pip version 10.0.1, however version 18.0 is available.\n",
      "You should consider upgrading via the 'python -m pip install --upgrade pip' command.\n"
     ]
    }
   ],
   "source": [
    "!pip install -q -U Slacker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "# Slacker \n",
    "from slacker import Slacker\n",
    "\n",
    "from sklearn.model_selection import train_test_split, StratifiedKFold\n",
    "import lightgbm as lgb\n",
    "\n",
    "# Plotting\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "%matplotlib inline\n",
    "plt.style.use('fivethirtyeight')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Get a Slack Legacy API Token\n",
    "\n",
    "https://api.slack.com/custom-integrations/legacy-tokens\n",
    "\n",
    "Store in a safe location (not on GitHub)!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Read in slack api token. Replace the line below with the location of your slack api token."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open('C:/Users/willk/OneDrive/Desktop/slack_api_python.txt', 'r') as f:\n",
    "    slack_api_token = f.read()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Authenticate with slack and print out channels to make sure everything worked."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Channel general Purpose: This channel is for workspace-wide communication and announcements. All members are in this channel. ID: CCCT28F08\n",
      "\n",
      "Channel python_content Purpose:  ID: CCEG5VCEM\n",
      "\n",
      "Channel random Purpose: A place for non-work-related flimflam, faffing, hodge-podge or jibber-jabber you'd prefer to keep out of more focused work-related channels. ID: CCDP3ES85\n",
      "\n",
      "Channel slack_interaction Purpose: To interact with Slack from Python ID: CCDC464LU\n",
      "\n",
      "Channel testing_exp Purpose: Experimental testing of interactions. ID: CCD27690R\n",
      "\n"
     ]
    }
   ],
   "source": [
    "slack = Slacker(slack_api_token)\n",
    "channels = slack.channels.list()\n",
    "\n",
    "for channel in channels.body['channels']:\n",
    "    print(f'Channel {channel[\"name\"]} Purpose: {channel[\"purpose\"][\"value\"]} ID: {channel[\"id\"]}\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'CCEG5VCEM'"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "slack.channels.create('python_content2')\n",
    "new_id = slack.channels.get_channel_id('python_content2')\n",
    "r = slack.channels.history(new_id)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'has_more': False,\n",
       " 'messages': [{'subtype': 'channel_join',\n",
       "   'text': '<@UCEKVNHPH> has joined the channel',\n",
       "   'ts': '1535161714.000200',\n",
       "   'type': 'message',\n",
       "   'user': 'UCEKVNHPH'}],\n",
       " 'ok': True}"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.body"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'CCDP3ES85'"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "slack.channels.get_channel_id('random')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<slacker.Response at 0x1f2136175c0>"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "slack.chat.post_message('random', 'Using no id')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<slacker.Response at 0x1f213cd2c50>"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "slack.chat.post_message(slack.channels.get_channel_id('random'), 'Using an id')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "channel_not_found",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mError\u001b[0m                                     Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-9-056f05d6c662>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mslack\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mchannels\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset_purpose\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'#testing_exp'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'Deep philosophical discussions around the water cooler.'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      2\u001b[0m \u001b[0mslack\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mchannels\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcreate\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'python_content'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      3\u001b[0m \u001b[0mslack\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mchannels\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset_purpose\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'python_content'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'Sharing great python related resources'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      4\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m \u001b[0mchannels\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mslack\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mchannels\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlist\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Anaconda3\\lib\\site-packages\\slacker\\__init__.py\u001b[0m in \u001b[0;36mset_purpose\u001b[1;34m(self, channel, purpose)\u001b[0m\n\u001b[0;32m    334\u001b[0m     \u001b[1;32mdef\u001b[0m \u001b[0mset_purpose\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mchannel\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mpurpose\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    335\u001b[0m         return self.post('channels.setPurpose',\n\u001b[1;32m--> 336\u001b[1;33m                          data={'channel': channel, 'purpose': purpose})\n\u001b[0m\u001b[0;32m    337\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    338\u001b[0m     \u001b[1;32mdef\u001b[0m \u001b[0mset_topic\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mchannel\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtopic\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Anaconda3\\lib\\site-packages\\slacker\\__init__.py\u001b[0m in \u001b[0;36mpost\u001b[1;34m(self, api, **kwargs)\u001b[0m\n\u001b[0;32m    121\u001b[0m         return self._request(\n\u001b[0;32m    122\u001b[0m             \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_session_post\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msession\u001b[0m \u001b[1;32melse\u001b[0m \u001b[0mrequests\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpost\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 123\u001b[1;33m             \u001b[0mapi\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    124\u001b[0m         )\n\u001b[0;32m    125\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\Anaconda3\\lib\\site-packages\\slacker\\__init__.py\u001b[0m in \u001b[0;36m_request\u001b[1;34m(self, method, api, **kwargs)\u001b[0m\n\u001b[0;32m     97\u001b[0m         \u001b[0mresponse\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mResponse\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mresponse\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtext\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     98\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mresponse\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msuccessful\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 99\u001b[1;33m             \u001b[1;32mraise\u001b[0m \u001b[0mError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mresponse\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0merror\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    100\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    101\u001b[0m         \u001b[1;32mreturn\u001b[0m \u001b[0mresponse\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mError\u001b[0m: channel_not_found"
     ]
    }
   ],
   "source": [
    "slack.channels.set_purpose('#testing_exp', 'Deep philosophical discussions around the water cooler.')\n",
    "slack.channels.create('python_content')\n",
    "slack.channels.set_purpose('python_content', 'Sharing great python related resources')\n",
    "\n",
    "channels = slack.channels.list()\n",
    "\n",
    "for channel in channels.body['channels']:\n",
    "    print(f'Channel {channel[\"name\"]} Purpose: {channel[\"purpose\"][\"value\"]}\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from PIL import Image\n",
    "import requests\n",
    "url = user['profile']['image_192']\n",
    "im = Image.open(requests.get(url, stream=True).raw)\n",
    "plt.imshow(im)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "PIL.Image.from"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from IPython.display import Image\n",
    "from PIL import Image\n",
    "import PIL\n",
    "users = slack.users.list()\n",
    "\n",
    "for user in users.body['members']:\n",
    "    # Print some information\n",
    "    print(f'\\nUser: {user[\"name\"]}, Real Name: {user[\"real_name\"]}, Time Zone: {user[\"tz_label\"]}.')\n",
    "    print(f'Current Status: {user[\"profile\"][\"status_text\"]}')\n",
    "    # Get image data and show\n",
    "    plt.figure(facecolor = 'w')\n",
    "    plt.imshow(Image.open(requests.get(user['profile']['image_192'], stream=True).raw))\n",
    "    plt.axis('off');\n",
    "    plt.grid('off');\n",
    "    plt.show();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.plot(np.random.randn(100), np.random.randn(100), 'ro')\n",
    "plt.savefig('first_plot.png')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "slack.files.upload('first_plot.png', channels = ['testing_exp', 'slack_interaction']);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Image(user['profile']['image_192'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "Image('https://secure.gravatar.com/avatar/f85b7564fd35d5c86054b95090052d94.jpg?s=192&d=https%3A%2F%2Fa.slack-edge.com%2F7fa9%2Fimg%2Favatars%2Fava_0025-192.png')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "users.body['members']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = slack.channels.list()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x.body"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
