Example #1
0
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        search = args[0]
        msg = str()

        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            self.handle_error(e, update)

        for entry in response:
            if search.lower() in entry["name"].lower():
                name = entry["name"]
                symbol = entry["symbol"]

                msg += f"`{name} - {symbol.upper()}`\n"

        if msg:
            msg = f"`Coin-search for '{search}'`\n\n" + msg
        else:
            msg = f"{emo.INFO} No coin with '*{search}*' found"

        update.message.reply_text(text=msg, parse_mode=ParseMode.MARKDOWN)
Example #2
0
    def _get_cmc_coin_id(self, ticker):
        self.cmc_coin_id = None

        for listing in APICache.get_cmc_coin_list():
            if ticker.upper() == listing["symbol"].upper():
                self.cmc_coin_id = listing["id"]
                break
Example #3
0
 def _get_cg_coin_id(self, coin):
     try:
         for entry in APICache.get_cg_coins_list():
             if entry["symbol"].lower() == coin.lower():
                 self.cg_coin_id = entry["id"]
                 break
     except Exception:
         self.cg_coin_id = None
Example #4
0
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        # Set tokens for Twitter access
        tw = twitter.Api(consumer_key=self._consumer_key,
                         consumer_secret=self._consumer_secret,
                         access_token_key=self._access_token_key,
                         access_token_secret=self._access_token_secret)

        coin = args[0].upper()

        # Get coin ID
        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            return self.handle_error(e, update)

        timeline = None
        for entry in response:
            if entry["symbol"].lower() == coin.lower():
                try:
                    data = CoinGecko().get_coin_by_id(entry["id"])
                except Exception as e:
                    return self.handle_error(e, update)

                coin_name = data["name"]
                tw_account = data["links"]["twitter_screen_name"]

                if tw_account:
                    timeline = tw.GetUserTimeline(screen_name=tw_account,
                                                  count=3,
                                                  include_rts=False,
                                                  trim_user=True,
                                                  exclude_replies=True)
                break

        if timeline:
            for tweet in [i.AsDict() for i in reversed(timeline)]:
                stats = f"{emo.HEART} {tweet['favorite_count']} " \
                        f"{emo.REPEAT} {tweet['retweet_count']}"

                msg = f"*Tweet from {coin_name}*\n" \
                      f"{tweet['created_at'].split('+')[0]}\n" \
                      f"{stats}\n\n" \
                      f"{tweet['text']}"

                update.message.reply_text(text=msg,
                                          parse_mode=ParseMode.MARKDOWN)
Example #5
0
    def _from_coinpaprika(self, coin):
        coin_id = str()

        for c in APICache.get_cp_coin_list():
            if c["symbol"] == coin:
                self.name = c["name"]
                coin_id = c["id"]

        if not coin_id:
            return None

        return webs.get_wp_coinpaprika(coin_id)
Example #6
0
    def _from_coinmarketcap(self, coin):
        slug = str()

        for listing in APICache.get_cmc_coin_list():
            if coin.upper() == listing["symbol"].upper():
                self.name = listing["name"].capitalize()
                slug = listing["website_slug"]
                break

        if not slug:
            return None

        return webs.get_wp_coinmarketcap(slug)
Example #7
0
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        coin = args[0].upper()
        msg = str()

        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            self.handle_error(e, update)

        for entry in response:
            if entry["symbol"].lower() == coin.lower():
                try:
                    data = CoinGecko().get_coin_by_id(entry["id"])
                except Exception as e:
                    self.handle_error(e, update)

                dev_data = data["developer_data"]

                for k, v in dev_data.items():
                    msg += f"`{k.title().replace('_', ' ')}: {str(v)}`\n"

                gh_links = data["links"]["repos_url"]["github"]

                if not gh_links:
                    break

                msg += "\n`GitHub links:`\n"

                for link in gh_links:
                    title_index = link.rfind("/")
                    msg += f"[{link[title_index+1:len(link)]}]({link})\n"

                break

        if msg:
            msg = f"`GitHub info for {coin}`\n\n" + msg
        else:
            msg = f"{emo.INFO} No developer data found for *{coin}*"

        update.message.reply_text(text=msg.replace("Pull Request", "PR"),
                                  parse_mode=ParseMode.MARKDOWN,
                                  disable_web_page_preview=True)
Example #8
0
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(
                text=f"Usage:\n{self.get_usage()}",
                parse_mode=ParseMode.MARKDOWN)
            return

        if len(args) > 1:
            update.message.reply_text(
                text=f"{emo.ERROR} Only one argument allowed",
                parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        coin = args[0].upper()
        msg = str()

        try:
            response = APICache.get_cp_coin_list()
        except Exception as e:
            return self.handle_error(e, update)

        for c in response:
            if c["symbol"] == coin:
                try:
                    cp_coin_detail = CoinPaprika().get_coin_by_id(c["id"])["team"]
                except Exception as e:
                    return self.handle_error(e, update)

                for p in cp_coin_detail:
                    details = utl.esc_md(f"/_people__{p['id'].replace('-', '_')}")
                    msg += f"`{p['name']}\n{p['position']}`\n{details}\n\n"
                break

        if not msg:
            update.message.reply_text(
                text=f"{emo.INFO} No team data for *{coin}*",
                parse_mode=ParseMode.MARKDOWN)
            return

        msg = f"`Team behind {coin}`\n\n{msg}"

        for message in utl.split_msg(msg):
            update.message.reply_text(
                text=message,
                parse_mode=ParseMode.MARKDOWN,
                disable_web_page_preview=True)
Example #9
0
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        coin = args[0].upper()
        data = None

        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            return self.handle_error(e, update)

        for entry in response:
            if entry["symbol"].lower() == coin.lower():
                try:
                    data = CoinGecko().get_coin_by_id(entry["id"])
                except Exception as e:
                    return self.handle_error(e, update)
                break

        if not data or not data["description"]["en"]:
            update.message.reply_text(text=f"{emo.INFO} No data for *{coin}*",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        coin_desc = data["description"]["en"]

        if len(coin_desc) > con.MAX_TG_MSG_LEN:
            url = f"https://www.coingecko.com/en/coins/{data['id']}"
            html_link = f'...\n\n<a href="{url}">Read whole description</a>'
            coin_desc = coin_desc[:(con.MAX_TG_MSG_LEN - 27)] + html_link

        update.message.reply_text(text=coin_desc,
                                  parse_mode=ParseMode.HTML,
                                  disable_web_page_preview=True)
Example #10
0
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(
                text=f"Usage:\n{self.get_usage()}",
                parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        coin = args[0].upper()
        data = None

        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            return self.handle_error(e, update)

        for entry in response:
            if entry["symbol"].lower() == coin.lower():
                try:
                    data = CoinGecko().get_coin_by_id(entry["id"])
                except Exception as e:
                    return self.handle_error(e, update)
                break

        if not data or not data["description"]["en"]:
            update.message.reply_text(
                text=f"{emo.INFO} No data for *{coin}*",
                parse_mode=ParseMode.MARKDOWN)
            return

        coin_desc = data["description"]["en"]

        for message in utl.split_msg(coin_desc):
            update.message.reply_text(
                text=message,
                parse_mode=ParseMode.HTML,
                disable_web_page_preview=True)
Example #11
0
    def get_action(self, bot, update, args):
        keywords = utl.get_kw(args)
        arg_list = utl.del_kw(args)

        if not arg_list:
            if not keywords.get(Keyword.INLINE):
                update.message.reply_text(
                    text=f"Usage:\n{self.get_usage()}",
                    parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        vs_cur = "usd"

        if "-" in arg_list[0]:
            pair = arg_list[0].split("-", 1)
            vs_cur = pair[1].lower()
            coin = pair[0].upper()
        else:
            coin = arg_list[0].upper()

        ath_date = str()
        ath_price = str()
        cur_price = str()
        ath_change = str()

        # Get coin ID
        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            return self.handle_error(e, update)

        for entry in response:
            if entry["symbol"].lower() == coin.lower():
                try:
                    coin_info = CoinGecko().get_coin_by_id(entry["id"])
                except Exception as e:
                    return self.handle_error(e, update)

                cur_price = coin_info["market_data"]["current_price"]
                ath_price = coin_info["market_data"]["ath"]
                ath_date = coin_info["market_data"]["ath_date"]
                ath_change = coin_info["market_data"]["ath_change_percentage"]
                break

        msg = str()

        for c in vs_cur.split(","):
            if c in ath_price:
                ath_p = format(ath_price[c])
                cur_p = format(cur_price[c], template=ath_p)
                change = format(ath_change[c], decimals=2)

                date_time = ath_date[c]
                date_ath = date_time[:10]
                date_list = date_ath.split("-")
                y = int(date_list[0])
                m = int(date_list[1])
                d = int(date_list[2])

                ath = date(y, m, d)
                now = datetime.date.today()

                ath_p_str = f"Price ATH: {ath_p} {c.upper()}\n"
                cur_p_str = f"Price NOW: {cur_p.rjust(len(ath_p))} {c.upper()}\n"

                msg += f"`" \
                       f"{date_ath} ({(now - ath).days} days ago)\n" \
                       f"{ath_p_str}" \
                       f"{cur_p_str}" \
                       f"Change: {change}%\n\n" \
                       f"`"

        if msg:
            msg = f"`All-Time High for {coin}`\n\n {msg}"
        else:
            msg = f"{emo.ERROR} Can't retrieve data for *{coin}*"

        if keywords.get(Keyword.INLINE):
            return msg

        self.send_msg(msg, update, keywords)
Example #12
0
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        msg = str()
        top = str()
        coin = str()
        vs_cur = "usd"

        if args[0].lower().startswith("top="):
            top = args[0][4:]

            if not top.isnumeric():
                update.message.reply_text(
                    text=f"{emo.ERROR} Value of `top` has to be a number",
                    parse_mode=ParseMode.MARKDOWN)
                return
            if int(top) > 100:
                update.message.reply_text(
                    text=f"{emo.ERROR} Max value for `top` is `100`",
                    parse_mode=ParseMode.MARKDOWN)
                return
        else:
            if "-" in args[0]:
                pair = args[0].split("-", 1)
                vs_cur = pair[0].lower()
                coin = pair[1].lower()
            else:
                coin = args[0].lower()

        if RateLimit.limit_reached(update):
            return

        # ---------- TOP VOLUME ----------

        if top:
            try:
                data = CoinGecko().get_coins_markets(vs_cur,
                                                     per_page=top,
                                                     page=1,
                                                     order="volume_desc",
                                                     sparkline=False)
            except Exception as e:
                return self.handle_error(e, update)

            count = 0
            for entry in data:
                count += 1

                name = entry["name"]
                symbol = entry["symbol"].upper()
                vol = utl.format(entry["total_volume"])

                msg += f"#{count} {name} ({symbol})\n" \
                       f"{vol} {vs_cur.upper()}\n\n"

            msg = f"Top {top} by Total Volume\n\n{msg}"

        # ---------- TOTAL VOLUME ----------

        else:
            data = None

            try:
                response = APICache.get_cg_coins_list()
            except Exception as e:
                return self.handle_error(e, update)

            # Get coin ID and data
            for entry in response:
                if entry["symbol"] == coin:
                    try:
                        data = CoinGecko().get_coins_markets(
                            vs_cur, ids=entry["id"], order="volume_desc")
                    except Exception as e:
                        return self.handle_error(e, update)
                    break

            if not data:
                update.message.reply_text(
                    text=f"{emo.ERROR} No data for *{coin}*",
                    parse_mode=ParseMode.MARKDOWN)
                return

            name = data[0]["name"]
            vol = utl.format(data[0]["total_volume"])

            msg = f"{name} ({coin.upper()})\n\n" \
                  f"Total Volume:\n" \
                  f"{vol} {vs_cur.upper()}"

        if not msg:
            msg = f"{emo.ERROR} Can't retrieve data for *{coin.upper()}*"

        update.message.reply_text(text=f"`{msg}`",
                                  parse_mode=ParseMode.MARKDOWN)
Example #13
0
    def get_action(self, bot, update, args):
        keywords = utl.get_kw(args)
        arg_list = utl.del_kw(args)

        if not arg_list:
            if not keywords.get(Keyword.INLINE):
                update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                          parse_mode=ParseMode.MARKDOWN)
            return

        time_frame = 72
        resolution = "HOUR"
        base_coin = "BTC"

        # Coin or pair
        if "-" in arg_list[0]:
            pair = arg_list[0].split("-", 1)
            base_coin = pair[1].upper()
            coin = pair[0].upper()
        else:
            coin = arg_list[0].upper()

        if coin == "BTC" and base_coin == "BTC":
            base_coin = "USD"

        if coin == base_coin:
            update.message.reply_text(
                text=f"{emo.ERROR} Can't compare *{coin}* to itself",
                parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        cmc_thread = threading.Thread(target=self._get_cmc_coin_id,
                                      args=[coin])
        cmc_thread.start()

        # Time frame
        if len(arg_list) > 1:
            if arg_list[1].lower().endswith(
                    "m") and arg_list[1][:-1].isnumeric():
                resolution = "MINUTE"
                time_frame = arg_list[1][:-1]
            elif arg_list[1].lower().endswith(
                    "h") and arg_list[1][:-1].isnumeric():
                resolution = "HOUR"
                time_frame = arg_list[1][:-1]
            elif arg_list[1].lower().endswith(
                    "d") and arg_list[1][:-1].isnumeric():
                resolution = "DAY"
                time_frame = arg_list[1][:-1]
            else:
                update.message.reply_text(
                    text=f"{emo.ERROR} Argument *{arg_list[1]}* is invalid",
                    parse_mode=ParseMode.MARKDOWN)
                return

        try:
            if resolution == "MINUTE":
                ohlcv = CryptoCompare().get_historical_ohlcv_minute(
                    coin, base_coin, time_frame)
            elif resolution == "HOUR":
                ohlcv = CryptoCompare().get_historical_ohlcv_hourly(
                    coin, base_coin, time_frame)
            elif resolution == "DAY":
                ohlcv = CryptoCompare().get_historical_ohlcv_daily(
                    coin, base_coin, time_frame)
            else:
                ohlcv = CryptoCompare().get_historical_ohlcv_hourly(
                    coin, base_coin, time_frame)
        except Exception as e:
            return self.handle_error(e, update)

        if ohlcv["Response"] == "Error":
            if ohlcv["Message"] == "limit is larger than max value.":
                update.message.reply_text(
                    text=f"{emo.ERROR} Time frame can't be larger "
                    f"then *{con.CG_DATA_LIMIT}* data points",
                    parse_mode=ParseMode.MARKDOWN)
                return
            elif ohlcv["Message"].startswith(
                    "There is no data for the symbol"):
                ohlcv = None
            else:
                update.message.reply_text(
                    text=f"{emo.ERROR} CoinGecko ERROR: {ohlcv['Message']}",
                    parse_mode=ParseMode.MARKDOWN)
                return

        ohlcv = ohlcv["Data"]

        if ohlcv:
            try:
                o = [value["open"] for value in ohlcv]
                h = [value["high"] for value in ohlcv]
                l = [value["low"] for value in ohlcv]
                c = [value["close"] for value in ohlcv]
                t = [value["time"] for value in ohlcv]
            except:
                return self.handle_error(f"No OHLC data for {coin}", update)

        if not ohlcv or utl.all_same(o, h, l, c):
            if base_coin != "BTC" and base_coin != "USD":
                update.message.reply_text(
                    text=f"{emo.ERROR} Base currency for "
                    f"*{coin}* can only be *BTC* or *USD*",
                    parse_mode=ParseMode.MARKDOWN)
                return

            # Time frame
            if len(arg_list) > 1:
                if resolution != "DAY":
                    update.message.reply_text(
                        text=f"{emo.ERROR} Timeframe for *{coin}* "
                        f"can only be specified in days",
                        parse_mode=ParseMode.MARKDOWN)
                    return
                else:
                    time_frame = int(time_frame)
            else:
                time_frame = 60  # Days

            try:
                cp_ohlc = APICache.get_cp_coin_list()
            except Exception as e:
                return self.handle_error(e, update)

            for c in cp_ohlc:
                if c["symbol"] == coin:
                    # Current datetime in seconds
                    t_now = time.time()
                    # Convert chart time span to seconds
                    time_frame = time_frame * 24 * 60 * 60
                    # Start datetime for chart in seconds
                    t_start = t_now - int(time_frame)

                    try:
                        ohlcv = CoinPaprika().get_historical_ohlc(
                            c["id"],
                            int(t_start),
                            end=int(t_now),
                            quote=base_coin.lower(),
                            limit=366)
                    except Exception as e:
                        return self.handle_error(e, update)

                    cp_api = True
                    break

            if not ohlcv:
                update.message.reply_text(
                    text=f"{emo.ERROR} No OHLC data for *{coin}* "
                    f"available or time frame too big",
                    parse_mode=ParseMode.MARKDOWN)
                return

            try:
                o = [value["open"] for value in ohlcv]
                h = [value["high"] for value in ohlcv]
                l = [value["low"] for value in ohlcv]
                c = [value["close"] for value in ohlcv]
                t = [
                    time.mktime(dau.parse(value["time_close"]).timetuple())
                    for value in ohlcv
                ]
            except:
                return self.handle_error(f"No OHLC data for {coin}", update)

        margin_l = 140
        tickformat = "0.8f"

        max_value = max(h)
        if max_value > 0.9:
            if max_value > 999:
                margin_l = 120
                tickformat = "0,.0f"
            else:
                margin_l = 125
                tickformat = "0.2f"

        try:
            fig = fif.create_candlestick(o, h, l, c, pd.to_datetime(t,
                                                                    unit='s'))
        except Exception as e:
            return self.handle_error(e, update)

        fig['layout']['yaxis'].update(tickformat=tickformat,
                                      tickprefix="   ",
                                      ticksuffix=f"  ")

        fig['layout'].update(title=dict(text=coin, font=dict(size=26)),
                             yaxis=dict(title=dict(text=base_coin,
                                                   font=dict(size=18)), ))

        fig['layout'].update(shapes=[{
            "type": "line",
            "xref": "paper",
            "yref": "y",
            "x0": 0,
            "x1": 1,
            "y0": c[len(c) - 1],
            "y1": c[len(c) - 1],
            "line": {
                "color": "rgb(50, 171, 96)",
                "width": 1,
                "dash": "dot"
            }
        }])

        fig['layout'].update(paper_bgcolor='rgb(233,233,233)',
                             plot_bgcolor='rgb(233,233,233)',
                             autosize=False,
                             width=800,
                             height=600,
                             margin=go.layout.Margin(l=margin_l,
                                                     r=50,
                                                     b=85,
                                                     t=100,
                                                     pad=4))

        cmc_thread.join()

        fig['layout'].update(images=[
            dict(source=f"{con.CMC_LOGO_URL_PARTIAL}{self.cmc_coin_id}.png",
                 opacity=0.8,
                 xref="paper",
                 yref="paper",
                 x=1.05,
                 y=1,
                 sizex=0.2,
                 sizey=0.2,
                 xanchor="right",
                 yanchor="bottom")
        ])

        self.send_photo(
            io.BufferedReader(BytesIO(pio.to_image(fig, format='jpeg'))),
            update, keywords)
Example #14
0
    def get_action(self, bot, update, args):
        keywords = utl.get_kw(args)
        arg_list = utl.del_kw(args)

        if not arg_list:
            if not keywords.get(Keyword.INLINE):
                update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                          parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        coin = arg_list[0].upper()
        data = None
        cgid = None

        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            return self.handle_error(e, update)

        # Get coin ID and data
        for entry in response:
            if entry["symbol"].upper() == coin:
                try:
                    data = CoinGecko().get_coin_by_id(entry["id"])
                except Exception as e:
                    return self.handle_error(e, update)

                cgid = entry["id"]
                break

        if not data:
            update.message.reply_text(text=f"{emo.ERROR} No data for *{coin}*",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        name = data["name"]
        symbol = data["symbol"].upper()

        rank_mc = data["market_cap_rank"]
        rank_cg = data["coingecko_rank"]

        cs = int(float(data['market_data']['circulating_supply']))
        sup_c = f"{utl.format(cs)} {symbol}"

        if data["market_data"]["total_supply"]:
            ts = int(float(data["market_data"]["total_supply"]))
            sup_t = f"{utl.format(ts)} {symbol}"
        else:
            sup_t = "N/A"

        usd = data["market_data"]["current_price"]["usd"]
        eur = data["market_data"]["current_price"]["eur"]
        btc = data["market_data"]["current_price"]["btc"]
        eth = data["market_data"]["current_price"]["eth"]

        p_usd = utl.format(usd, force_length=True)
        p_eur = utl.format(eur, force_length=True, template=p_usd)
        p_btc = utl.format(btc, force_length=True, template=p_usd)
        p_eth = utl.format(eth, force_length=True, template=p_usd)

        p_usd = "{:>12}".format(p_usd)
        p_eur = "{:>12}".format(p_eur)
        p_btc = "{:>12}".format(p_btc)
        p_eth = "{:>12}".format(p_eth)

        # Do not display BTC or ETH price if coin is BTC or ETH
        btc_str = "" if coin == "BTC" else f"BTC {p_btc}\n"
        eth_str = "" if coin == "ETH" else f"ETH {p_eth}\n"

        v_24h = utl.format(
            int(float(data["market_data"]["total_volume"]["usd"])))
        m_cap = utl.format(int(float(
            data["market_data"]["market_cap"]["usd"])))

        if data["market_data"]["price_change_percentage_1h_in_currency"]:
            c_1h = data["market_data"][
                "price_change_percentage_1h_in_currency"]["usd"]
            c1h = utl.format(float(c_1h), decimals=2, force_length=True)
            h1 = "{:>10}".format(f"{c1h}%")
        else:
            h1 = "{:>10}".format("N/A")

        if data["market_data"]["price_change_percentage_24h_in_currency"]:
            c_1d = data["market_data"][
                "price_change_percentage_24h_in_currency"]["usd"]
            c1d = utl.format(float(c_1d), decimals=2, force_length=True)
            d1 = "{:>10}".format(f"{c1d}%")
        else:
            d1 = "{:>10}".format("N/A")

        if data["market_data"]["price_change_percentage_7d_in_currency"]:
            c_1w = data["market_data"][
                "price_change_percentage_7d_in_currency"]["usd"]
            c1w = utl.format(float(c_1w), decimals=2, force_length=True)
            w1 = "{:>10}".format(f"{c1w}%")
        else:
            w1 = "{:>10}".format("N/A")

        if data["market_data"]["price_change_percentage_30d_in_currency"]:
            c_1m = data["market_data"][
                "price_change_percentage_30d_in_currency"]["usd"]
            c1m = utl.format(float(c_1m), decimals=2, force_length=True)
            m1 = "{:>10}".format(f"{c1m}%")
        else:
            m1 = "{:>10}".format("N/A")

        if data["market_data"]["price_change_percentage_1y_in_currency"]:
            c_1y = data["market_data"][
                "price_change_percentage_1y_in_currency"]["usd"]
            c1y = utl.format(float(c_1y), decimals=2, force_length=True)
            y1 = "{:>10}".format(f"{c1y}%")
        else:
            y1 = "{:>10}".format("N/A")

        msg = f"`" \
              f"{name} ({symbol})\n\n" \
              f"USD {p_usd}\n" \
              f"EUR {p_eur}\n" \
              f"{btc_str}" \
              f"{eth_str}\n" \
              f"Hour  {h1}\n" \
              f"Day   {d1}\n" \
              f"Week  {w1}\n" \
              f"Month {m1}\n" \
              f"Year  {y1}\n\n" \
              f"Market Cap Rank: {rank_mc}\n" \
              f"Coin Gecko Rank: {rank_cg}\n\n" \
              f"Volume 24h: {v_24h} USD\n" \
              f"Market Cap: {m_cap} USD\n" \
              f"Circ. Supp: {sup_c}\n" \
              f"Total Supp: {sup_t}\n\n" \
              f"`" \
              f"Stats on [CoinGecko](https://www.coingecko.com/en/coins/{cgid}) & " \
              f"[Coinlib](https://coinlib.io/coin/{coin}/{coin})"

        if keywords.get(Keyword.INLINE):
            return msg

        self.send_msg(msg, update, keywords)
Example #15
0
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        coin = args[0].upper()
        msg = str()

        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            self.handle_error(e, update)

        for entry in response:
            if entry["symbol"].lower() == coin.lower():
                try:
                    data = CoinGecko().get_coin_by_id(entry["id"])
                except Exception as e:
                    self.handle_error(e, update)

                if "ico_data" not in data:
                    break

                ico_start = data["ico_data"]["ico_start_date"][:10]
                ico_end = data["ico_data"]["ico_end_date"][:10]
                raised = data["ico_data"]["total_raised"]
                raised_cur = data["ico_data"]["total_raised_currency"]

                pre_sale_c = data["ico_data"]["quote_pre_sale_currency"]
                pre_sale_a = data["ico_data"]["base_pre_sale_amount"]
                pre_sale_p = data["ico_data"]["quote_pre_sale_amount"]

                pub_sale_c = data["ico_data"]["quote_public_sale_currency"]
                pub_sale_a = data["ico_data"]["base_public_sale_amount"]
                pub_sale_p = data["ico_data"]["quote_public_sale_amount"]

                kyc_req = data["ico_data"]["kyc_required"]

                raised = utl.format(raised) if raised is not None else raised

                if pre_sale_a:
                    pre_sale_a = utl.format(pre_sale_a, symbol=coin)
                if pre_sale_p:
                    pre_sale_p = utl.format(pre_sale_p, symbol=pre_sale_c)

                if pub_sale_a:
                    pub_sale_a = utl.format(pub_sale_a, symbol=coin)
                if pub_sale_p:
                    pub_sale_p = utl.format(pub_sale_p, symbol=pub_sale_c)

                if pre_sale_a:
                    pre_sale_str = f"{pre_sale_a} {coin} for {pre_sale_p} {pre_sale_c}\n"
                else:
                    pre_sale_str = "None\n"

                if pub_sale_a:
                    pub_sale_str = f"{pub_sale_a} {coin} for {pub_sale_p} {pub_sale_c}\n"
                else:
                    pub_sale_str = "None\n"

                msg = f"`" \
                      f"Start:    {ico_start}\n" \
                      f"End:      {ico_end}\n" \
                      f"Raised:   {raised} {raised_cur}\n" \
                      f"Pre-Sale: {pre_sale_str}" \
                      f"Pub-Sale: {pub_sale_str}" \
                      f"KYC:      {'Yes' if kyc_req == True else 'No'}" \
                      f"`"
                break

        if msg:
            msg = f"`ICO data for {coin}`\n\n" + msg
        else:
            msg = f"{emo.INFO} No ICO data for *{coin}*"

        update.message.reply_text(text=msg, parse_mode=ParseMode.MARKDOWN)
Example #16
0
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        vs_cur = "btc,eth,usd,eur"

        if "-" in args[0]:
            pair = args[0].split("-", 1)
            vs_cur = pair[0].lower()
            coin = pair[1].upper()
        else:
            coin = args[0].upper()

        if len(args) > 1 and utl.is_number(args[1]):
            qty = args[1]
        else:
            update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        prices = dict()

        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            return self.handle_error(e, update)

        # Get coin ID
        for entry in response:
            if entry["symbol"].upper() == coin:
                try:
                    data = CoinGecko().get_coin_by_id(entry["id"])
                except Exception as e:
                    return self.handle_error(e, update)

                prices = data["market_data"]["current_price"]
                break

        try:
            qty_float = float(qty)
        except Exception:
            update.message.reply_text(
                text=f"{emo.ERROR} Quantity '{qty}' not valid",
                parse_mode=ParseMode.MARKDOWN)
            return

        msg = str()

        for c in vs_cur.split(","):
            if c in prices:
                value = utl.format(prices[c] * qty_float)
                msg += f"`{c.upper()}: {value}`\n"

        if msg:
            msg = f"`Value of {qty} {coin}`\n\n" + msg
        else:
            msg = f"{emo.ERROR} Can't retrieve data for *{coin}*"

        update.message.reply_text(text=msg, parse_mode=ParseMode.MARKDOWN)
Example #17
0
    def get_action(self, bot, update, args):
        # TODO: Do this in every plugin
        keywords = utl.get_kw(args)
        arg_list = utl.del_kw(args)

        # TODO: Do this in most other plugins
        if not arg_list:
            if not keywords.get(Keyword.INLINE):
                update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                          parse_mode=ParseMode.MARKDOWN)
            return

        vs_cur = str()

        if "-" in arg_list[0]:
            pair = arg_list[0].split("-", 1)
            vs_cur = pair[1].upper()
            coin = pair[0].upper()
        else:
            coin = arg_list[0].upper()

        exchange = str()
        if len(arg_list) > 1:
            exchange = arg_list[1]

        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            return self.handle_error(e, update)

        coin_id = str()
        coin_name = str()
        for entry in response:
            if entry["symbol"].upper() == coin:
                coin_id = entry["id"]
                coin_name = entry["name"]
                break

        if RateLimit.limit_reached(update):
            return

        cg = CoinGecko()
        msg = str()

        if exchange:
            try:
                result = cg.get_coin_by_id(coin_id)
            except Exception as e:
                return self.handle_error(e, update)

            if result:
                vs_list = list()

                if vs_cur:
                    vs_list = vs_cur.split(",")

                for ticker_len in result["tickers"]:
                    if ticker_len["market"]["name"].upper() == exchange.upper(
                    ):
                        if ticker_len["base"] != coin:
                            base_coin = ticker_len["base"]
                        else:
                            base_coin = ticker_len["target"]

                        if vs_list:
                            if base_coin in vs_list:
                                price = utl.format(ticker_len["last"],
                                                   force_length=True)
                                msg += f"`{base_coin}: {price}`\n"
                        else:
                            price = utl.format(ticker_len["last"],
                                               force_length=True)
                            msg += f"`{base_coin}: {price}`\n"
        else:
            if not vs_cur:
                if coin == "BTC":
                    vs_cur = "ETH,USD,EUR"
                elif coin == "ETH":
                    vs_cur = "BTC,USD,EUR"
                else:
                    vs_cur = "BTC,ETH,USD,EUR"

            try:
                result = cg.get_simple_price(coin_id, vs_cur)
            except Exception as e:
                return self.handle_error(e, update)

            if result:
                for symbol, price in next(iter(result.values())).items():
                    if symbol in utl.get_fiat_list():
                        if decimal.Decimal(
                                str(price)).as_tuple().exponent > -3:
                            price = utl.format(price,
                                               decimals=2,
                                               force_length=True)
                        else:
                            price = utl.format(price, force_length=True)
                    else:
                        price = utl.format(price, force_length=True)

                    msg += f"`{symbol.upper()}: {price}`\n"

        if msg:
            if exchange:
                ticker_len = 0
                for line in msg.split("\n"):
                    length = len(line[:line.find(":")])
                    if ticker_len < length:
                        ticker_len = length

                message = str()
                for line in msg.split("\n"):
                    if line:
                        lst = line.split(" ")
                        index = ticker_len + 2 + len(lst[1]) - len(lst[0])
                        price = "{1:>{0}}".format(index, lst[1])
                        message += f"{lst[0]}{price}\n"

                msg = f"`{coin} ({coin_name}) on {exchange.capitalize()}`\n\n" + message
            else:
                msg = f"`{coin} ({coin_name})`\n\n" + msg

            # Add link to source of data (CoinGecko)
            msg += f"\n[Details on CoinGecko]({self.CG_URL}{coin_id})"
        else:
            msg = f"{emo.ERROR} Can't retrieve data for *{coin}*"

        if keywords.get(Keyword.INLINE):
            return msg

        self.send_msg(msg, update, keywords)
Example #18
0
    def get_action(self, bot, update, args):
        vs_cur = str()

        if not args:
            if update.message:
                update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                          parse_mode=ParseMode.MARKDOWN)
            return

        if "-" in args[0]:
            pair = args[0].split("-", 1)
            vs_cur = pair[0].upper()
            coin = pair[1].upper()
        else:
            coin = args[0].upper()

        exchange = str()
        if len(args) > 1:
            exchange = args[1]

        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            self.handle_error(e, update)

        coin_id = str()
        for entry in response:
            if entry["symbol"].upper() == coin:
                coin_id = entry["id"]
                break

        if RateLimit.limit_reached(update):
            return

        cg = CoinGecko()
        msg = str()

        if exchange:
            try:
                result = cg.get_coin_by_id(coin_id)
            except Exception as e:
                self.handle_error(e, update)

            if result:
                vs_list = list()

                if vs_cur:
                    vs_list = vs_cur.split(",")

                for ticker in result["tickers"]:
                    if ticker["market"]["name"].upper() == exchange.upper():
                        base_coin = ticker["target"]
                        if vs_list:
                            if base_coin in vs_list:
                                price = utl.format(ticker["last"],
                                                   force_length=True)
                                msg += f"`{base_coin}: {price}`\n"
                        else:
                            price = utl.format(ticker["last"],
                                               force_length=True)
                            msg += f"`{base_coin}: {price}`\n"
        else:
            if not vs_cur:
                if coin == "BTC":
                    vs_cur = "ETH,USD,EUR"
                elif coin == "ETH":
                    vs_cur = "BTC,USD,EUR"
                else:
                    vs_cur = "BTC,ETH,USD,EUR"

            try:
                result = cg.get_simple_price(coin_id, vs_cur)
            except Exception as e:
                self.handle_error(e, update)

            if result:
                for symbol, price in next(iter(result.values())).items():
                    if symbol in utl.get_fiat_list():
                        if decimal.Decimal(
                                str(price)).as_tuple().exponent > -3:
                            price = utl.format(price,
                                               decimals=2,
                                               force_length=True)
                        else:
                            price = utl.format(price, force_length=True)
                    else:
                        price = utl.format(price, force_length=True)

                    msg += f"`{symbol.upper()}: {price}`\n"

        if msg:
            if exchange:
                msg = f"`Price of {coin} on {exchange.capitalize()}`\n\n" + msg
            else:
                msg = f"`Price of {coin}`\n\n" + msg
        else:
            msg = f"{emo.ERROR} Can't retrieve data for *{coin}*"

        if update.message:
            update.message.reply_text(text=msg, parse_mode=ParseMode.MARKDOWN)
        else:
            return msg
Example #19
0
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        coin = args[0].upper()
        msg = str()

        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            return self.handle_error(e, update)

        for entry in response:
            if entry["symbol"].lower() == coin.lower():
                try:
                    data = CoinGecko().get_coin_by_id(entry["id"])
                except Exception as e:
                    return self.handle_error(e, update)

                home_lst = list(filter(None, data["links"]["homepage"]))
                block_lst = list(filter(None,
                                        data["links"]["blockchain_site"]))
                annou_lst = list(
                    filter(None, data["links"]["announcement_url"]))
                chat_lst = list(filter(None, data["links"]["chat_url"]))
                forum_lst = list(
                    filter(None, data["links"]["official_forum_url"]))
                twitter = data["links"]["twitter_screen_name"]
                facebook = data["links"]["facebook_username"]
                btctalk = data["links"]["bitcointalk_thread_identifier"]
                telegram = data["links"]["telegram_channel_identifier"]
                reddit = data["links"]["subreddit_url"]

                fb_likes = data["community_data"]["facebook_likes"]
                tw_follow = data["community_data"]["twitter_followers"]
                rd_subsc = data["community_data"]["reddit_subscribers"]
                tg_usr_cnt = data["community_data"][
                    "telegram_channel_user_count"]

                msg = f"`Social data for {data['name']} ({coin})`\n\n"

                if home_lst:
                    url = utl.esc_md(utl.url(home_lst))
                    msg += f"`Homepage:`\n{url}\n"
                if block_lst:
                    url = utl.esc_md(utl.url(block_lst))
                    msg += f"`Block Explorer:`\n{url}\n"
                if annou_lst:
                    url = utl.esc_md(utl.url(annou_lst))
                    msg += f"`Announcements:`\n{url}\n"
                if chat_lst:
                    url = utl.esc_md(utl.url(chat_lst))
                    msg += f"`Chat:`\n{url}\n"
                if forum_lst:
                    url = utl.esc_md(utl.url(forum_lst))
                    msg += f"`Forum:`\n{url}\n"
                if twitter:
                    tw_follow = utl.format(tw_follow)
                    url = utl.esc_md(f"{self.TW_URL}{twitter}")
                    msg += f"`Twitter ({tw_follow} Followers):`\n{url}\n"
                if facebook:
                    fb_likes = utl.format(fb_likes)
                    url = utl.esc_md(f"{self.FB_URL}{facebook}")
                    msg += f"`Facebook ({fb_likes} Likes):`\n{url}\n"
                if btctalk:
                    url = utl.esc_md(f"{self.BT_URL}{btctalk}")
                    msg += f"`BitcoinTalk:`\n{url}\n"
                if telegram:
                    tg_usr_cnt = utl.format(tg_usr_cnt)
                    url = utl.esc_md(f"{self.TG_URL}{telegram}")
                    msg += f"`Telegram ({tg_usr_cnt} Users):`\n{url}\n"
                if reddit:
                    rd_subsc = utl.format(rd_subsc)
                    url = utl.esc_md(f"{utl.url(reddit)}")
                    msg += f"`Reddit ({rd_subsc} Subscribers):`\n{url}\n"

                break

        if not msg:
            update.message.reply_text(
                text=f"{emo.ERROR} No data found for *{coin}*",
                parse_mode=ParseMode.MARKDOWN)
            return

        update.message.reply_text(text=msg,
                                  disable_web_page_preview=True,
                                  parse_mode=ParseMode.MARKDOWN)
Example #20
0
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        coin = args[0].upper()
        coin_info = None

        volume = False
        if len(args) > 1:
            if args[1].lower().startswith("vol"):
                volume = True

        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            return self.handle_error(e, update)

        # Get coin ID and data
        for entry in response:
            if entry["symbol"].upper() == coin:
                try:
                    coin_info = CoinGecko().get_coin_by_id(entry["id"])
                except Exception as e:
                    return self.handle_error(e, update)
                break

        if not coin_info or not coin_info["tickers"]:
            update.message.reply_text(text=f"{emo.ERROR} No data for *{coin}*",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        # Sort markets by volume
        if volume:
            data = sorted(coin_info["tickers"],
                          key=lambda k: float(k["volume"]),
                          reverse=True)

            count = len(data)
            if count > 10:
                count = 10

            msg = str()
            for i in range(count):
                vs_cur = data[i]["target"]
                exchange = data[i]["market"]["name"]
                vol_usd = data[i]["converted_volume"]["usd"]
                vol_usd = utl.format(vol_usd, decimals=2, force_length=True)

                msg += f"{exchange} - {vs_cur}\nVolume: {vol_usd} USD\n\n"

            update.message.reply_text(text=f"`Exchanges that trade {coin}`\n"
                                      f"`Top 10 sorted by volume\n\n{msg}`",
                                      parse_mode=ParseMode.MARKDOWN)

        else:
            exchanges = set()
            for ticker in coin_info["tickers"]:
                exchanges.add(ticker['market']['name'])

            exchanges = "\n".join(sorted(exchanges))

            update.message.reply_text(
                text=f"`Exchanges that trade {coin}`\n\n`{exchanges}`",
                parse_mode=ParseMode.MARKDOWN)
Example #21
0
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(
                text=f"Usage:\n{self.get_usage()}",
                parse_mode=ParseMode.MARKDOWN)
            return

        if RateLimit.limit_reached(update):
            return

        vs_cur = "usd"

        if "-" in args[0]:
            pair = args[0].split("-", 1)
            vs_cur = pair[1].lower()
            coin = pair[0].upper()
        else:
            coin = args[0].upper()

        data = None

        try:
            response = APICache.get_cg_coins_list()
        except Exception as e:
            return self.handle_error(e, update)

        # Get coin ID and data
        for entry in response:
            if entry["symbol"].upper() == coin:
                try:
                    data = CoinGecko().get_coin_by_id(entry["id"])
                except Exception as e:
                    return self.handle_error(e, update)
                break

        if not data:
            update.message.reply_text(
                text=f"{emo.INFO} No data for *{coin}*",
                parse_mode=ParseMode.MARKDOWN)
            return

        name = data["name"]
        symbol = data["symbol"].upper()

        if data["market_data"]["price_change_percentage_1h_in_currency"]:
            c_1h = data["market_data"]["price_change_percentage_1h_in_currency"][vs_cur]
            c1h = utl.format(float(c_1h), decimals=2, force_length=True)
            h1 = "{:>10}".format(f"{c1h}%")
        else:
            h1 = "{:>10}".format("N/A")

        if data["market_data"]["price_change_percentage_24h_in_currency"]:
            c_1d = data["market_data"]["price_change_percentage_24h_in_currency"][vs_cur]
            c1d = utl.format(float(c_1d), decimals=2, force_length=True)
            d1 = "{:>10}".format(f"{c1d}%")
        else:
            d1 = "{:>10}".format("N/A")

        if data["market_data"]["price_change_percentage_7d_in_currency"]:
            c_1w = data["market_data"]["price_change_percentage_7d_in_currency"][vs_cur]
            c1w = utl.format(float(c_1w), decimals=2, force_length=True)
            w1 = "{:>10}".format(f"{c1w}%")
        else:
            w1 = "{:>10}".format("N/A")

        if data["market_data"]["price_change_percentage_30d_in_currency"]:
            c_1m = data["market_data"]["price_change_percentage_30d_in_currency"][vs_cur]
            c1m = utl.format(float(c_1m), decimals=2, force_length=True)
            m1 = "{:>10}".format(f"{c1m}%")
        else:
            m1 = "{:>10}".format("N/A")

        if data["market_data"]["price_change_percentage_1y_in_currency"]:
            c_1y = data["market_data"]["price_change_percentage_1y_in_currency"]["usd"]
            c1y = utl.format(float(c_1y), decimals=2, force_length=True)
            y1 = "{:>10}".format(f"{c1y}%")
        else:
            y1 = "{:>10}".format("N/A")

        update.message.reply_text(
            text=f"`"
                 f"{name} ({symbol}) in {vs_cur.upper()}\n\n"
                 f"Hour  {h1}\n"
                 f"Day   {d1}\n"
                 f"Week  {w1}\n"
                 f"Month {m1}\n"
                 f"Year  {y1}\n\n"
                 f"`",
            parse_mode=ParseMode.MARKDOWN,
            disable_web_page_preview=True)
    def get_action(self, bot, update, args):
        if not args:
            update.message.reply_text(text=f"Usage:\n{self.get_usage()}",
                                      parse_mode=ParseMode.MARKDOWN)
            return

        msg = str()
        top = str()
        exchange = str()

        if args[0].lower().startswith("top="):
            top = args[0][4:]
        else:
            exchange = args[0]

        # ---------- TOP EXCHANGES ----------

        if top:
            if not top.isnumeric():
                update.message.reply_text(
                    text=f"{emo.ERROR} Value of `top` has to be a number",
                    parse_mode=ParseMode.MARKDOWN)
                return
            if int(top) > 100:
                update.message.reply_text(
                    text=f"{emo.ERROR} Max value for `top` is `100`",
                    parse_mode=ParseMode.MARKDOWN)
                return

            if RateLimit.limit_reached(update):
                return

            try:
                response = APICache.get_cg_exchanges_list()
            except Exception as e:
                self.handle_error(e, update)

            exchanges = sorted(response,
                               key=lambda k: float(k["trade_volume_24h_btc"]),
                               reverse=True)

            for i in range(int(top)):
                ex = exchanges[i]

                nr = f"#{i+1}"
                name = ex["name"]
                volume = ex["trade_volume_24h_btc"]

                msg += f"`{nr} {name}\n{utl.format(volume)} BTC`\n\n"

            msg = f"`Top {top} exchanges by 24h volume`\n\n{msg}"

        # ---------- EXCHANGE DETAILS ----------

        else:
            if RateLimit.limit_reached(update):
                return

            try:
                response = APICache.get_cg_exchanges_list()
            except Exception as e:
                self.handle_error(e, update)

            for ex in response:
                clean_ex = ex["name"].replace(" ", "")
                if exchange.lower() in clean_ex.lower():
                    nme = ex["name"] if ex["name"] else "N/A"
                    est = ex["year_established"] if ex[
                        "year_established"] else "N/A"
                    cnt = ex["country"] if ex["country"] else "N/A"
                    des = ex["description"] if ex[
                        "description"] else "(No description available)"
                    url = ex["url"] if ex["url"] else "(No link available)"
                    vol = ex["trade_volume_24h_btc"] if ex[
                        "trade_volume_24h_btc"] else "N/A"

                    msg += f"`{nme}`\n" \
                           f"{utl.url(url)}\n\n" \
                           f"`Country:     {cnt}`\n" \
                           f"`Volume 24h:  {utl.format(vol)} BTC`\n" \
                           f"`Established: {est}`\n\n" \
                           f"`{utl.remove_html_links(des)}`\n\n\n" \

        if not msg:
            update.message.reply_text(
                text=f"{emo.INFO} No exchange '{exchange}' found",
                parse_mode=ParseMode.MARKDOWN)
            return

        update.message.reply_text(text=msg,
                                  parse_mode=ParseMode.MARKDOWN,
                                  disable_web_page_preview=True)