Home » Python » python – line 1233, in __getitem__ raise KeyError(key)-Exceptionshub

python – line 1233, in __getitem__ raise KeyError(key)-Exceptionshub

Posted by: admin February 24, 2020 Leave a comment

Questions:

I want to create telegram bot. I cloned some repository from github and now i am trying to run this project. I created bot wath the help of @BotFather and he gave me token. When i try to run this project with “python3 bot.py” I get error ” line 1233, in getitem
raise KeyError(key)

I have file config.ini and I should fill it properly(I know it from tutorial) but I really don’t understand how can I fill it properly 🙁
Could somebody help me, I would be really grateful. I just want to try to run this bot and see how it works and write my own bot in future.

config.ini:

[Telegram]
token=<- here I wrote my token, which I got from @BotFather

[API]
client_id= <- I don't know what should I write here
app_id= <- I don't know what should I write here
app_id= <- I don't know what should I write here
shared_key= <- I don't know what should I write here

Instead of token I am using my own token

bot.py:

# -*- coding:utf-8 -*-

import re
from sys import path
from decimal import Decimal

from configparser import ConfigParser

from telegram import ParseMode, Emoji
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
from telegram.ext.dispatcher import run_async

from mdapi import DataStorage, MDApiConnector
from fundamental import FundamentalApi

import logging

# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    level=logging.INFO)

logger = logging.getLogger(__name__)

# read config
config = ConfigParser()
config.read_file(open('config.ini'))

# create connectors to API
api = MDApiConnector(
    client_id=config['API']['client_id'],
    app_id=config['API']['app_id'],
    key=config['API']['shared_key']
)

fapi = FundamentalApi()

# Create telegram poller with token from settings
up = Updater(token=config['Telegram']['token'], workers=32)
dispatcher = up.dispatcher

# start stock storage
storage = DataStorage(api)
storage.start()


# Welcome message
def start(bot, update):
    msg = "Привет, {user_name}! \n\n" + \
    "Меня можно спросить об акциях фондового рынка США \n" + \
    "и я покажу их оценку P/E и текущую цену. \n\n" + \
    "Например: расскажи об AAPL или NVDA"

    # Send the message
    bot.send_message(chat_id=update.message.chat_id,
                     text=msg.format(
                         user_name=update.message.from_user.first_name,
                         bot_name=bot.name))

@run_async
def process(bot, update):
    if update.message.text.find("брокера посоветуешь") > 0:
        update.message.reply_text("Лично я рекомендую EXANTE!")
        return

    tickers = re.findall(r'[A-Z]{1,4}', update.message.text)

    msg = ""
    for ticker in tickers:
        stock = storage.stocks.get(ticker)
        if not stock: continue

        eps = fapi.request(ticker).get('EarningsShare')
        if not eps:
            logger.warning("Can't fetch EPS for {}".format(ticker))
            continue

        price = api.get_last_ohlc_bar(stock['id'])
        ratio = Decimal("%.4f" % price['close']) / Decimal(eps)

        msg += "{ticker} ({name}, {exchange}): EPS {eps}, P/E {ratio}, цена ${price} \n".format(
            ticker = ticker,
            name = stock['description'],
            exchange = stock['exchange'],
            ratio = "%.2f" % ratio,
            price = price['close'],
            eps = eps
        )

    if not msg:
        msg = "Не удалось получить данные по тикерам из запроса :(\n" +\
              "Попробуйте спросить о чем-то популярном, вроде GOOG или AAPL."

    bot.send_message(chat_id=update.message.chat_id, text=msg)


if __name__ == "__main__":
    # Add handlers to dispatcher
    dispatcher.add_handler(CommandHandler("start", start))
    dispatcher.add_handler(MessageHandler(Filters.text, process))

    up.start_polling()
    up.idle()

fundamental.py:

from datetime import datetime

import requests


class FundamentalApi():
    def __init__(self):
        self.cache = {}

    def request(self, symbol):
        now = datetime.now()

        result = self.cache.get(symbol)

        # if data is already stored for current day
        if result and (now - result[1]).days < 1:
            return result[0]

        params = {
            "q": "select EarningsShare from yahoo.finance.quotes where symbol = '{}'".format(symbol),
            "env": "store://datatables.org/alltableswithkeys",
            "format": "json"
        }

        url = "https://query.yahooapis.com/v1/public/yql"
        response = requests.get(url, params=params)
        response.raise_for_status()

        data = response.json()['query']['results']['quote']
        self.cache[symbol] = (data, now)

        return self.cache[symbol][0]

mdapi.py:

import time
from threading import Thread
from datetime import datetime

import jwt
import requests

import logging

# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    level=logging.INFO)

logger = logging.getLogger(__name__)

# token expiration time in seconds
EXPIRATION = 3600
API_URL = "https://api-demo.exante.eu/md/1.0"


class MDApiConnector():
    token = (None, None)
    algo = "HS256"

    def __init__(self, client_id, app_id, key):
        self.client_id = client_id
        self.app_id = app_id
        self.key = key

    def __get_token(self):
        now = datetime.now()

        # if there is token and it's not expired yet
        if self.token[0] and (now - self.token[1]).total_seconds() < EXPIRATION:
            return self.token[0]

        claims = {
            "iss": self.client_id,
            "sub": self.app_id,
            "aud": ["symbols", "ohlc"],
            "iat": int(now.timestamp()),
            "exp": int(now.timestamp()) + EXPIRATION
        }

        new_token = str(jwt.encode(claims, self.key, self.algo), 'utf-8')
        self.token = (new_token, now)

        return new_token

    def __request(self, endpoint, params=None):
        token = self.__get_token()
        result = requests.get(API_URL + endpoint,
                              headers={"Authorization": "Bearer %s" % token},
                              params=params)
        result.raise_for_status()
        return result.json()

    def get_stocks(self):
        stocks = self.__request("/types/STOCK")
        return {x['ticker']: {"id": x["id"], "exchange": x["exchange"], "description": x["description"]}
                for x in stocks if x.get("country") == "US"}

    def get_last_ohlc_bar(self, symbolId):
        # NB: we use internal symbolId, not ticker

        # 86400 (sec) - day duration
        ohlc = self.__request("/ohlc/%s/86400" % symbolId, {"size": 1})
        return ohlc[0]


class DataStorage(Thread):
    def __init__(self, connector):
        super().__init__()
        self.connector = connector
        self.stocks = {}

    def run(self):
        while True:
            timeout = 15 * 60  # 15 minutes
            try:
                self.stocks = self.connector.get_stocks()
            except Exception as e:
                logger.error(e)
                timeout = 30  # re-read in case of exception

            time.sleep(timeout)

init.py:

# -*- coding:utf-8 -*-

import re
from sys import path

from configparser import ConfigParser

from telegram import ParseMode, Emoji
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters


config = ConfigParser()
config.read_file(open('config.ini'))

# Create telegram poller with token from settings
up = Updater(token=config[‘Api’]['token'])
dispatcher = up.dispatcher

# Welcome message
def start(bot, update):
    msg = "Hello {user_name}! I'm {bot_name}. Ask me about stocks!"

    # Send the message
    bot.send_message(chat_id=update.message.chat_id,
                     text=msg.format(
                         user_name=update.message.from_user.first_name,
                         bot_name=bot.name))

def process(bot, update):
    msg = "I will try to show info on {tickers}"
    tickers = re.findall(r'[A-Z]{1,4}', update.message.text)

    bot.send_message(chat_id=update.message.chat_id,
                     text=msg.format(tickers=", ".join(tickers)))

def main():
    # Add handlers to dispatcher
    dispatcher.add_handler(CommandHandler("start", start))
    dispatcher.add_handler(MessageHandler(Filters.text, process))

    # Start the program
    up.start_polling()

    up.idle()

if __name__ == '__main__':
    main()

How to&Answers: