├── src ├── __init__.py ├── msgs │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-38.pyc │ │ ├── bot_msgs.cpython-38.pyc │ │ └── msg_generator.cpython-38.pyc │ ├── msg_generator.py │ └── bot_msgs.py ├── tests │ ├── __init__.py │ └── test_github_api.py ├── services │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-38.pyc │ │ └── github_api.cpython-38.pyc │ └── github_api.py ├── __pycache__ │ ├── env.cpython-38.pyc │ └── __init__.cpython-38.pyc └── bot.py ├── .gitignore ├── .vim └── coc-settings.json ├── pyproject.toml ├── LICENSE ├── README.md └── poetry.lock /src/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/msgs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/services/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | src/env.py 2 | __pycache__/ 3 | *.pyc 4 | -------------------------------------------------------------------------------- /src/__pycache__/env.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devssa/dev-jobs-bot/HEAD/src/__pycache__/env.cpython-38.pyc -------------------------------------------------------------------------------- /src/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devssa/dev-jobs-bot/HEAD/src/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.pythonPath": "/home/kaiten/.cache/pypoetry/virtualenvs/dev-jobs-bot-x3SL82g8-py3.8/bin/python" 3 | } -------------------------------------------------------------------------------- /src/msgs/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devssa/dev-jobs-bot/HEAD/src/msgs/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /src/msgs/__pycache__/bot_msgs.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devssa/dev-jobs-bot/HEAD/src/msgs/__pycache__/bot_msgs.cpython-38.pyc -------------------------------------------------------------------------------- /src/msgs/__pycache__/msg_generator.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devssa/dev-jobs-bot/HEAD/src/msgs/__pycache__/msg_generator.cpython-38.pyc -------------------------------------------------------------------------------- /src/services/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devssa/dev-jobs-bot/HEAD/src/services/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /src/services/__pycache__/github_api.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devssa/dev-jobs-bot/HEAD/src/services/__pycache__/github_api.cpython-38.pyc -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "dev-jobs-bot" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["kaetaen "] 6 | license = "MIT" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.8" 10 | requests = "^2.25.0" 11 | pyTelegramBotAPI = "^3.7.4" 12 | schedule = "^1.0.0" 13 | 14 | [tool.poetry.dev-dependencies] 15 | pylint = "^2.6.0" 16 | jedi = "^0.17.2" 17 | 18 | [build-system] 19 | requires = ["poetry-core>=1.0.0"] 20 | build-backend = "poetry.core.masonry.api" 21 | -------------------------------------------------------------------------------- /src/msgs/msg_generator.py: -------------------------------------------------------------------------------- 1 | from random import choice 2 | 3 | 4 | def parse_jobs(job): 5 | title = job['title'] 6 | raw_date = job['created_at'].split('T')[0] 7 | year, month, day = raw_date.split('-') 8 | link = job['html_url'] 9 | emoji = choice([ 10 | '👩🏿‍💻', '👨🏿‍💻', 11 | '👨🏻‍💻','👩🏻‍💻' 12 | ]) 13 | 14 | msg = f'{emoji} Vaga: {title}\n'\ 15 | f'📅 Data de publicação: {day}/{month}/{year}\n'\ 16 | f'ℹ️ Mais informações: {link}\n\n' 17 | 18 | return msg 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/tests/test_github_api.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | from os.path import dirname, join, abspath 3 | sys.path.insert(0, abspath(join(dirname(__file__), '..'))) 4 | 5 | import unittest 6 | 7 | from services.github_api import GitHubApi 8 | 9 | 10 | class TestGitHubAPI(unittest.TestCase): 11 | def setUp(self): 12 | self.api = GitHubApi() 13 | 14 | def test_API_status_not_ok(self): 15 | self.assertEqual(self.api.status, 200, 'The status_code doesn\'t ok.') 16 | 17 | def test_case_client_side_error(self): 18 | self.assertFalse(self.api.status > 300 and self.api.status < 500, 'Client-side error.') 19 | 20 | def test_case_server_side_error(self): 21 | self.assertFalse(self.api.status >= 500, 'Server-side error.') 22 | 23 | 24 | if __name__ == '__main__': 25 | unittest.main() 26 | 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Rubens dos Santos 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/services/github_api.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from requests import api 4 | from requests import status_codes 5 | sys.path.append("..") 6 | 7 | import requests 8 | import json 9 | from datetime import date 10 | 11 | import env 12 | from msgs import msg_generator 13 | 14 | class GitHubApi: 15 | def __init__(self): 16 | self.url = env.COMMUNITY_GH_API_ISSUES 17 | self.issues = [] 18 | self.status = self.api_issues() 19 | 20 | def api_issues(self): 21 | response = requests.get(self.url) 22 | if (response.status_code <= 300): 23 | data = json.loads(response.content) 24 | self.issues = data 25 | 26 | elif (response.status_code > 300 and response.status_code < 500): 27 | self.issues.append('Client-Side Error') 28 | return 200 29 | 30 | elif (response.status_code >= 500): 31 | self.issues.append('Server-side error') 32 | return 200 33 | 34 | return response.status_code 35 | 36 | def get_jobs(self): 37 | urls = [] 38 | today = date.today().strftime('%Y-%m-%d') 39 | 40 | for issue in self.issues: 41 | created_at = issue['created_at'].split('T')[0] 42 | updated_at = issue['updated_at'].split('T')[0] 43 | 44 | if (created_at == today or updated_at == today): 45 | urls.append(issue['html_url']) 46 | 47 | return urls 48 | 49 | def last_jobs(self, num=10): 50 | msg = '' 51 | if num == 1: 52 | msg = f'🗒️Essa foi a última vagas lançada 🗒️\n\n' 53 | else: 54 | msg = f'🗒️ Essas foram as {num} últimas vagas lançadas 🗒️\n\n' 55 | 56 | for issue in self.issues[:num]: 57 | msg += msg_generator.parse_jobs(issue) 58 | 59 | return msg 60 | -------------------------------------------------------------------------------- /src/bot.py: -------------------------------------------------------------------------------- 1 | import telebot 2 | import env 3 | from services.github_api import GitHubApi 4 | from msgs import bot_msgs as msg 5 | from random import choice 6 | 7 | bot = telebot.TeleBot(env.TOKEN) 8 | bot.remove_webhook() 9 | 10 | @bot.message_handler(commands=['jobs']) 11 | def send_jobs(message): 12 | jobs = GitHubApi().get_jobs() 13 | 14 | if jobs: 15 | for job in jobs: 16 | bot.send_message(message.chat.id, job) 17 | else: 18 | bot.send_message( 19 | message.chat.id, 20 | msg.NOT_JOBS_MSG, 21 | disable_web_page_preview=None, 22 | ) 23 | 24 | 25 | @bot.message_handler(commands=['about']) 26 | def about_me(message): 27 | bot.send_message(message.chat.id, msg.ABOUT_MSG) 28 | 29 | 30 | @bot.message_handler(commands=['last']) 31 | def get_last_jobs(message): 32 | num_jobs = message.text.split(' ') 33 | if (len(num_jobs) > 1): 34 | try: 35 | range_jobs = int(num_jobs[1]) 36 | if (range_jobs <= 10 and range_jobs != 0): 37 | jobs = GitHubApi().last_jobs(range_jobs) 38 | bot.send_message( 39 | message.chat.id, 40 | jobs, 41 | disable_web_page_preview=True 42 | ) 43 | else: 44 | raise ValueError 45 | 46 | except ValueError: 47 | bot.send_message(message.chat.id, 'Informe um valor entre 1 e 10') 48 | bot.send_message( 49 | message.chat.id, 50 | jobs, 51 | disable_web_page_preview=True 52 | ) 53 | 54 | 55 | @bot.message_handler(commands=['hint']) 56 | def get_hint(message): 57 | bot.send_message( 58 | message.chat.id, 59 | choice(msg.HINTS_MSG), 60 | disable_web_page_preview=True 61 | ) 62 | 63 | 64 | if __name__ == '__main__': 65 | bot.polling() 66 | -------------------------------------------------------------------------------- /src/msgs/bot_msgs.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('..') 3 | import env 4 | 5 | NOT_JOBS_MSG = f''' 6 | ⚠ ️Nenhuma vaga foi divulgada hoje. 7 | 8 | Verifique as vagas dos dias anteriores no repositório da comunidade. 9 | Pode ser que as mesmas ainda não tenham sido preenchidas. 10 | 11 | {env.COMMUNITY_GH_ISSUES} 12 | ''' 13 | 14 | ABOUT_MSG = f''' 15 | {env.BOT_NAME} é um bot para exibir as vagas da área de desenvolvimento e afins divulgadas no GitHub da comunidade {env.COMMUNITY_NAME}. 16 | 17 | Site: {env.COMMUNITY_SITE} 18 | GitHub: {env.COMMUNITY_GH} 19 | ''' 20 | 21 | HINTS_MSG = [ 22 | '"Foque numa tecnologia e fique bom nela, '\ 23 | 'evite ficar pulando de uma tecnologia para outra."\n'\ 24 | '— João Paulo', 25 | 26 | '"Seja curiosa(o) e esteja preparada(o) para estar sempre estudando'\ 27 | ' algo novo."\n'\ 28 | '— Elisete Vidotti\n\n'\ 29 | 'Github: lizvidotti91', 30 | 31 | '"Estudar sempre e persistência!"\n'\ 32 | '— Jailton Dantas\n\n'\ 33 | 'GitHub: jndantas', 34 | 35 | '"Crie um currículo com um objetivo bem definido. '\ 36 | 'Por exemplo: back-end Java, front-end React"\n'\ 37 | '— Anônimo', 38 | 39 | '"Git, inglês, e lógica de programação"\n'\ 40 | '— Anônimo', 41 | 42 | '"Escolha aprender o básico de linguagens mainstream, e que tem bastante '\ 43 | 'mercado (tipo Javascript e PHP), aprende a fazer um pouco de tudo, '\ 44 | 'criar api, aprender um pouco de frontend, e se joga!\n'\ 45 | '— Anônimo', 46 | 47 | '"Foco, acima de tudo, foco em seus objetivos!"\n'\ 48 | '— Anônimo', 49 | 50 | '"Ame programação, sem amor você não dura muito nessa área"\n'\ 51 | '— Anônimo', 52 | 53 | '"Tenha um portifólio no Github"\n'\ 54 | '— Anônimo', 55 | 56 | '"Trabalhar nas soft-skills para mim é algo muito importante."\n'\ 57 | '— Anônimo', 58 | 59 | '"Estude SQL."\n'\ 60 | '— David Meth\n\n'\ 61 | 'Github Linkedin: me42th' 62 | ] 63 | 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dev Jobs Bot 2 | 3 | 4 | > _"Os seres humanos são alérgicos à mudança. Adoram dizer: 'Nós sempre fizemos isto desta maneira.' Eu tento lutar contra isso. É por isso que eu tenho um relógio na minha parede que roda no sentido anti-horário."_
5 | > – Grace Hopper 6 | 7 |

8 |

via GIPHY

9 | 10 | ## Descrição 11 | 12 | Dev Jobs Bot é um bot genérico que disponibiliza vagas de emprego que são divulgados no GitHub através das issues de um determinado repositório. 13 | Antes de utilizar este bot em sua comunidade, recomendo este tutorial de como criar um bot no Telegram. 14 | 15 | ## Como surgiu 16 | 17 | Ao participar do grupo do Telegram da comunidade Onde Codar em Salvador, eu percebi que as vagas eram inseridas em um repositório especifico da comunidade e divulgadas através das issues do mesmo. Percebi que este é um padrão na maioria das comunidades, e como quase toda comunidade tem um canal no Telegram (sim, é lá que os devs se escondem!) e reconhecendo este padrão... porque não unir o útil ao agradável e automatizar o acesso as vagas por terceiros direto do próprio telegram? 18 | 19 | ## Uso 20 | 21 | ### Configurações iniciais 22 | É necessário renomear o env.example.py para env.py, e preencher todas as variáveis constantes com as seguintes informações: 23 | 24 | * TOKEN: str => deve conter o token da API do telegram para se comunicar com o bot 25 | * BOT_NAME: str => o nome do seu bot. 26 | * COMMUNITY_SITE: str => o site da sua comunidade. 27 | * COMMUNITY_GH: str => o link do GitHub da comunidade. 28 | * COMMUNITY_GH_ISSUES: str => o link das issues do repositório de vagas no GitHub da comunidade. 29 | * COMMUNITY_GH_API_ISSUES: str => o link da API do GitHub para acessar as issues do repositório de vagas. 30 | * Exemplo: https://api.github.com/repos/{mantenedor}/{repositório}/issues. 31 | * COMMUNITY_NAME: str => nome da comunidade. 32 | 33 | ### Comandos 34 | 35 | Copie esses comandos e insira na seção de comandos do bot, esta etapa é responsabilidade do BotFather, o deus dos Bots. 36 | ``` 37 | jobs - Verifique as vagas lançadas hoje! 38 | last - Configura as últimas dez vagas 39 | about - Sobre este bot 40 | hint - Dicas da comunidade 41 | ``` 42 | Os comandos são auto-explicativos, certo? Preferi utilizar o inglês por convenção, se tiver algo contra... o Tio Sam vai bater na sua porta! Brincadeira, é só forkar e fazer o que você quiser hahahahaha. 43 | 44 | ## Agradecimentos 45 | 46 | Alguns módulos de código aberto foram utilizados neste projeto, é sempre bom fazer uma referência a quem facilita nosso dia-a-dia e contribui direta ou indiretamente para um mundo melhor. 47 | 48 | * pyTelegramBotAPI: fácil de usar, prático, poderoso e... pythônico (todos os metódos em snake_case, isso é poesia para mim). 49 | * requests: aquele módulo _massa_ pra quem quer fazer scraping, consumir APIs ou só tem preguiça de aprender o urllib, mesmo ele sendo mais rápido hahaha. 50 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "astroid" 3 | version = "2.5" 4 | description = "An abstract syntax tree for Python with inference support." 5 | category = "dev" 6 | optional = false 7 | python-versions = ">=3.6" 8 | 9 | [package.dependencies] 10 | lazy-object-proxy = ">=1.4.0" 11 | wrapt = ">=1.11,<1.13" 12 | 13 | [[package]] 14 | name = "certifi" 15 | version = "2020.12.5" 16 | description = "Python package for providing Mozilla's CA Bundle." 17 | category = "main" 18 | optional = false 19 | python-versions = "*" 20 | 21 | [[package]] 22 | name = "chardet" 23 | version = "4.0.0" 24 | description = "Universal encoding detector for Python 2 and 3" 25 | category = "main" 26 | optional = false 27 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 28 | 29 | [[package]] 30 | name = "colorama" 31 | version = "0.4.4" 32 | description = "Cross-platform colored terminal text." 33 | category = "dev" 34 | optional = false 35 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 36 | 37 | [[package]] 38 | name = "idna" 39 | version = "2.10" 40 | description = "Internationalized Domain Names in Applications (IDNA)" 41 | category = "main" 42 | optional = false 43 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 44 | 45 | [[package]] 46 | name = "isort" 47 | version = "5.7.0" 48 | description = "A Python utility / library to sort Python imports." 49 | category = "dev" 50 | optional = false 51 | python-versions = ">=3.6,<4.0" 52 | 53 | [package.extras] 54 | pipfile_deprecated_finder = ["pipreqs", "requirementslib"] 55 | requirements_deprecated_finder = ["pipreqs", "pip-api"] 56 | colors = ["colorama (>=0.4.3,<0.5.0)"] 57 | 58 | [[package]] 59 | name = "jedi" 60 | version = "0.17.2" 61 | description = "An autocompletion tool for Python that can be used for text editors." 62 | category = "dev" 63 | optional = false 64 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 65 | 66 | [package.dependencies] 67 | parso = ">=0.7.0,<0.8.0" 68 | 69 | [package.extras] 70 | qa = ["flake8 (==3.7.9)"] 71 | testing = ["Django (<3.1)", "colorama", "docopt", "pytest (>=3.9.0,<5.0.0)"] 72 | 73 | [[package]] 74 | name = "lazy-object-proxy" 75 | version = "1.5.2" 76 | description = "A fast and thorough lazy object proxy." 77 | category = "dev" 78 | optional = false 79 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 80 | 81 | [[package]] 82 | name = "mccabe" 83 | version = "0.6.1" 84 | description = "McCabe checker, plugin for flake8" 85 | category = "dev" 86 | optional = false 87 | python-versions = "*" 88 | 89 | [[package]] 90 | name = "parso" 91 | version = "0.7.1" 92 | description = "A Python Parser" 93 | category = "dev" 94 | optional = false 95 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 96 | 97 | [package.extras] 98 | testing = ["docopt", "pytest (>=3.0.7)"] 99 | 100 | [[package]] 101 | name = "pylint" 102 | version = "2.7.1" 103 | description = "python code static checker" 104 | category = "dev" 105 | optional = false 106 | python-versions = "~=3.6" 107 | 108 | [package.dependencies] 109 | astroid = "2.5.0" 110 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 111 | isort = ">=4.2.5,<6" 112 | mccabe = ">=0.6,<0.7" 113 | toml = ">=0.7.1" 114 | 115 | [package.extras] 116 | docs = ["sphinx (>=3.2,<4.0)", "python-docs-theme"] 117 | 118 | [[package]] 119 | name = "pytelegrambotapi" 120 | version = "3.7.6" 121 | description = "Python Telegram bot api." 122 | category = "main" 123 | optional = false 124 | python-versions = "*" 125 | 126 | [package.dependencies] 127 | requests = "*" 128 | 129 | [package.extras] 130 | json = ["ujson"] 131 | redis = ["redis (>=3.4.1)"] 132 | 133 | [[package]] 134 | name = "requests" 135 | version = "2.25.1" 136 | description = "Python HTTP for Humans." 137 | category = "main" 138 | optional = false 139 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 140 | 141 | [package.dependencies] 142 | certifi = ">=2017.4.17" 143 | chardet = ">=3.0.2,<5" 144 | idna = ">=2.5,<3" 145 | urllib3 = ">=1.21.1,<1.27" 146 | 147 | [package.extras] 148 | security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] 149 | socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] 150 | 151 | [[package]] 152 | name = "schedule" 153 | version = "1.0.0" 154 | description = "Job scheduling for humans." 155 | category = "main" 156 | optional = false 157 | python-versions = ">=3.6" 158 | 159 | [[package]] 160 | name = "toml" 161 | version = "0.10.2" 162 | description = "Python Library for Tom's Obvious, Minimal Language" 163 | category = "dev" 164 | optional = false 165 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 166 | 167 | [[package]] 168 | name = "urllib3" 169 | version = "1.26.3" 170 | description = "HTTP library with thread-safe connection pooling, file post, and more." 171 | category = "main" 172 | optional = false 173 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 174 | 175 | [package.extras] 176 | brotli = ["brotlipy (>=0.6.0)"] 177 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] 178 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 179 | 180 | [[package]] 181 | name = "wrapt" 182 | version = "1.12.1" 183 | description = "Module for decorators, wrappers and monkey patching." 184 | category = "dev" 185 | optional = false 186 | python-versions = "*" 187 | 188 | [metadata] 189 | lock-version = "1.1" 190 | python-versions = "^3.8" 191 | content-hash = "69c60fa2129f1ec4c59ae2a7fd5bcbee03fc0884e7972068425f187ac19bf81e" 192 | 193 | [metadata.files] 194 | astroid = [ 195 | {file = "astroid-2.5-py3-none-any.whl", hash = "sha256:87ae7f2398b8a0ae5638ddecf9987f081b756e0e9fc071aeebdca525671fc4dc"}, 196 | {file = "astroid-2.5.tar.gz", hash = "sha256:b31c92f545517dcc452f284bc9c044050862fbe6d93d2b3de4a215a6b384bf0d"}, 197 | ] 198 | certifi = [ 199 | {file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"}, 200 | {file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"}, 201 | ] 202 | chardet = [ 203 | {file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"}, 204 | {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"}, 205 | ] 206 | colorama = [ 207 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 208 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 209 | ] 210 | idna = [ 211 | {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, 212 | {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, 213 | ] 214 | isort = [ 215 | {file = "isort-5.7.0-py3-none-any.whl", hash = "sha256:fff4f0c04e1825522ce6949973e83110a6e907750cd92d128b0d14aaaadbffdc"}, 216 | {file = "isort-5.7.0.tar.gz", hash = "sha256:c729845434366216d320e936b8ad6f9d681aab72dc7cbc2d51bedc3582f3ad1e"}, 217 | ] 218 | jedi = [ 219 | {file = "jedi-0.17.2-py2.py3-none-any.whl", hash = "sha256:98cc583fa0f2f8304968199b01b6b4b94f469a1f4a74c1560506ca2a211378b5"}, 220 | {file = "jedi-0.17.2.tar.gz", hash = "sha256:86ed7d9b750603e4ba582ea8edc678657fb4007894a12bcf6f4bb97892f31d20"}, 221 | ] 222 | lazy-object-proxy = [ 223 | {file = "lazy-object-proxy-1.5.2.tar.gz", hash = "sha256:5944a9b95e97de1980c65f03b79b356f30a43de48682b8bdd90aa5089f0ec1f4"}, 224 | {file = "lazy_object_proxy-1.5.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:e960e8be509e8d6d618300a6c189555c24efde63e85acaf0b14b2cd1ac743315"}, 225 | {file = "lazy_object_proxy-1.5.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:522b7c94b524389f4a4094c4bf04c2b02228454ddd17c1a9b2801fac1d754871"}, 226 | {file = "lazy_object_proxy-1.5.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:3782931963dc89e0e9a0ae4348b44762e868ea280e4f8c233b537852a8996ab9"}, 227 | {file = "lazy_object_proxy-1.5.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:429c4d1862f3fc37cd56304d880f2eae5bd0da83bdef889f3bd66458aac49128"}, 228 | {file = "lazy_object_proxy-1.5.2-cp35-cp35m-win32.whl", hash = "sha256:cd1bdace1a8762534e9a36c073cd54e97d517a17d69a17985961265be6d22847"}, 229 | {file = "lazy_object_proxy-1.5.2-cp35-cp35m-win_amd64.whl", hash = "sha256:ddbdcd10eb999d7ab292677f588b658372aadb9a52790f82484a37127a390108"}, 230 | {file = "lazy_object_proxy-1.5.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ecb5dd5990cec6e7f5c9c1124a37cb2c710c6d69b0c1a5c4aa4b35eba0ada068"}, 231 | {file = "lazy_object_proxy-1.5.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:b6577f15d5516d7d209c1a8cde23062c0f10625f19e8dc9fb59268859778d7d7"}, 232 | {file = "lazy_object_proxy-1.5.2-cp36-cp36m-win32.whl", hash = "sha256:c8fe2d6ff0ff583784039d0255ea7da076efd08507f2be6f68583b0da32e3afb"}, 233 | {file = "lazy_object_proxy-1.5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:fa5b2dee0e231fa4ad117be114251bdfe6afe39213bd629d43deb117b6a6c40a"}, 234 | {file = "lazy_object_proxy-1.5.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1d33d6f789697f401b75ce08e73b1de567b947740f768376631079290118ad39"}, 235 | {file = "lazy_object_proxy-1.5.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:57fb5c5504ddd45ed420b5b6461a78f58cbb0c1b0cbd9cd5a43ad30a4a3ee4d0"}, 236 | {file = "lazy_object_proxy-1.5.2-cp37-cp37m-win32.whl", hash = "sha256:e7273c64bccfd9310e9601b8f4511d84730239516bada26a0c9846c9697617ef"}, 237 | {file = "lazy_object_proxy-1.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6f4e5e68b7af950ed7fdb594b3f19a0014a3ace0fedb86acb896e140ffb24302"}, 238 | {file = "lazy_object_proxy-1.5.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cadfa2c2cf54d35d13dc8d231253b7985b97d629ab9ca6e7d672c35539d38163"}, 239 | {file = "lazy_object_proxy-1.5.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:e7428977763150b4cf83255625a80a23dfdc94d43be7791ce90799d446b4e26f"}, 240 | {file = "lazy_object_proxy-1.5.2-cp38-cp38-win32.whl", hash = "sha256:2f2de8f8ac0be3e40d17730e0600619d35c78c13a099ea91ef7fb4ad944ce694"}, 241 | {file = "lazy_object_proxy-1.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:38c3865bd220bd983fcaa9aa11462619e84a71233bafd9c880f7b1cb753ca7fa"}, 242 | {file = "lazy_object_proxy-1.5.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:8a44e9901c0555f95ac401377032f6e6af66d8fc1fbfad77a7a8b1a826e0b93c"}, 243 | {file = "lazy_object_proxy-1.5.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fa7fb7973c622b9e725bee1db569d2c2ee64d2f9a089201c5e8185d482c7352d"}, 244 | {file = "lazy_object_proxy-1.5.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:71a1ef23f22fa8437974b2d60fedb947c99a957ad625f83f43fd3de70f77f458"}, 245 | {file = "lazy_object_proxy-1.5.2-cp39-cp39-win32.whl", hash = "sha256:ef3f5e288aa57b73b034ce9c1f1ac753d968f9069cd0742d1d69c698a0167166"}, 246 | {file = "lazy_object_proxy-1.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:37d9c34b96cca6787fe014aeb651217944a967a5b165e2cacb6b858d2997ab84"}, 247 | ] 248 | mccabe = [ 249 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 250 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 251 | ] 252 | parso = [ 253 | {file = "parso-0.7.1-py2.py3-none-any.whl", hash = "sha256:97218d9159b2520ff45eb78028ba8b50d2bc61dcc062a9682666f2dc4bd331ea"}, 254 | {file = "parso-0.7.1.tar.gz", hash = "sha256:caba44724b994a8a5e086460bb212abc5a8bc46951bf4a9a1210745953622eb9"}, 255 | ] 256 | pylint = [ 257 | {file = "pylint-2.7.1-py3-none-any.whl", hash = "sha256:a251b238db462b71d25948f940568bb5b3ae0e37dbaa05e10523f54f83e6cc7e"}, 258 | {file = "pylint-2.7.1.tar.gz", hash = "sha256:81ce108f6342421169ea039ff1f528208c99d2e5a9c4ca95cfc5291be6dfd982"}, 259 | ] 260 | pytelegrambotapi = [ 261 | {file = "pyTelegramBotAPI-3.7.6.tar.gz", hash = "sha256:859136cbd50e99922e1ea495d4ebe8235b2cb10fe419a5421f28855249db4278"}, 262 | ] 263 | requests = [ 264 | {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"}, 265 | {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, 266 | ] 267 | schedule = [ 268 | {file = "schedule-1.0.0-py2.py3-none-any.whl", hash = "sha256:82369250700af61af40bbf38efc8698560aaba8fa3e58eec7209c20aa05b9d02"}, 269 | {file = "schedule-1.0.0.tar.gz", hash = "sha256:1654cf70860a6d4d58236c98b0f1bb71521cc2a4bbf031b6cc39c96e77d59a91"}, 270 | ] 271 | toml = [ 272 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 273 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 274 | ] 275 | urllib3 = [ 276 | {file = "urllib3-1.26.3-py2.py3-none-any.whl", hash = "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80"}, 277 | {file = "urllib3-1.26.3.tar.gz", hash = "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73"}, 278 | ] 279 | wrapt = [ 280 | {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, 281 | ] 282 | --------------------------------------------------------------------------------