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)
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
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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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)
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)
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)