def get_player(pid=0): ''' Create a Player tuple from an ID Request the Dotabuff, join the ID and scan the page with BS4 ''' if not isinstance(pid, int): raise Exception("Invalid Player ID type given") s = "http://www.dotabuff.com/players" uri = "/".join([s, str(pid)]) doc = re_get(uri, headers={'User-Agent':'Mozilla/5.0'}) bs = BeautifulSoup(doc.text, 'html.parser') pnm = bs.title.string.split(" ").pop(0) # should fetch the player's Name # row finding block rws = bs.find_all('div', class_='r-row') # first 10 have to retrieve a-href URIs hrs = [parse_hero(x.find('a').get('href')) for x in rws[:10]] # fetch match URIs after the 10th row mts = [parse_id(h.get('data-link-to')) for h in rws[10:]] # finish return Player(pid, pnm, hrs, mts)
def get_player(pid=0): ''' Create a Player tuple from an ID Request the Dotabuff, join the ID and scan the page with BS4 ''' if not isinstance(pid, int): raise Exception("Invalid Player ID type given") s = "http://www.dotabuff.com/players" uri = "/".join([s, str(pid)]) doc = re_get(uri, headers={'User-Agent': 'Mozilla/5.0'}) bs = BeautifulSoup(doc.text, 'html.parser') pnm = bs.title.string.split(" ").pop(0) # should fetch the player's Name # row finding block rws = bs.find_all('div', class_='r-row') # first 10 have to retrieve a-href URIs hrs = [parse_hero(x.find('a').get('href')) for x in rws[:10]] # fetch match URIs after the 10th row mts = [parse_id(h.get('data-link-to')) for h in rws[10:]] # finish return Player(pid, pnm, hrs, mts)
def get_bs(url): """ Return a parser of the given URL fragment /content/something-id -> BS(ROOT_URL/content/something-id) Applies a ton of filtering/replacing so we don't get bad characters """ text = re_get(craft_url(url)).text text = "".join([c for c in text if c in printable]) text = text.replace("\n", " ").replace("\xa0", " ") return BS(text, 'html.parser')
async def dota_id(msg, mobj): """ Registers a user's Discord ID with a Dota 2 player ID This will be used by the automated Dota 2 match parser service The string given is tested against OpenDota's API to see if it's valid """ if len(msg) > 30: return await client.send_message(mobj.channel, "Bro that's too long") r = re_get(f"{OPENDOTA_API}/players/{msg.strip()}") if r.status_code != 200: return await client.send_message(mobj.channel, "Invalid Dota 2 ID") fname = shared_data(f"{mobj.author.id}.dota") with open(fname, 'w') as f: f.write(msg.strip()) return await client.send_message(mobj.channel, "Registered Player ID {msg.strip()}")
async def dota_id(msg, mobj): """ Register's a user's Discord ID and associates it with a Dota ID This is used to retrieve a user's last played match from OpenDota The string must be tested against OpenDota's API to see if it's valid """ if len(msg) > 30: return await client.send_message(mobj.channel, "Bro that's too long") r = re_get(f"{OPENDOTA_API}/players/{msg.strip()}") if r.status_code != 200: return await client.send_message(mobj.channel, "Invalid Dota ID") fname = bot_data(f"{mobj.author.id}.txt") print(fname) with open(fname, 'w') as f: f.write(msg.strip()) print("Returning") return await client.send_message(mobj.channel, "Registered your Dota ID")
def db_sample_request(): """Retrieve data of many products using a Search Requests""" url = "https://fr.openfoodfacts.org/cgi/search.pl?" params = { "action": "process", "tagtype_0": "purchase_places", "tag_contains_0": "contains", "tag_0": "france", "sort_by": "unique_scans_n", "page_size": 1000, "json": 1 } res = re_get(url, params=params) if res.status_code != 200: raise ConnectionError() return res.json()
async def hoogle(msg, mobj): """ Send a Haskell type signature to Hoogle and return the first result If no results, error string Ex1: !hoogle (a -> b) -> M a -> M b Ex2: !hoogle >>= """ if contains_badwords(msg): return if msg == "": return await client.send_message(mobj.channel, "Nothing sent") base_url = "https://www.haskell.org/hoogle/?hoogle={}" search = BS(re_get(base_url.format(url_replace(msg))).text, "html.parser") answers = search.find_all("div", class_="ans") if not answers: return await client.send_message(mobj.channel, "Nothing was found, bud") res = answers[0] text = res.text url = res.find("a", class_="a")["href"] return await client.send_message(mobj.channel, "{}\n{}".format(text, url))
def get_match(mid): ''' ''' if not isinstance(mid, int): raise Exception("Invalid Match ID type given") s = "http://www.dotabuff.com/matches" uri = "/".join([s, str(mid)]) doc = re_get(uri, headers={'User-Agent':'Mozilla/5.0'}) bs = BeautifulSoup(doc.text, 'html.parser') # Get the winning team winner = bs.find('div', class_='match-result').text.split(' ').pop(0) # Get the player rows radi_rows = bs.find_all('tr', class_='faction-radiant') dire_rows = bs.find_all('tr', class_='faction-dire') # Convert the rows into PStats for the teams radi_team = [to_pstat(row) for row in radi_rows] dire_team = [to_pstat(row) for row in dire_rows] return Match(mid, radi_team, dire_team, winner)
def get_match(mid): ''' ''' if not isinstance(mid, int): raise Exception("Invalid Match ID type given") s = "http://www.dotabuff.com/matches" uri = "/".join([s, str(mid)]) doc = re_get(uri, headers={'User-Agent': 'Mozilla/5.0'}) bs = BeautifulSoup(doc.text, 'html.parser') # Get the winning team winner = bs.find('div', class_='match-result').text.split(' ').pop(0) # Get the player rows radi_rows = bs.find_all('tr', class_='faction-radiant') dire_rows = bs.find_all('tr', class_='faction-dire') # Convert the rows into PStats for the teams radi_team = [to_pstat(row) for row in radi_rows] dire_team = [to_pstat(row) for row in dire_rows] return Match(mid, radi_team, dire_team, winner)
async def ddg(msg, mobj): """ Search DuckDuckGo and post the first result Example: !ddg let me google that for you """ try: if msg == "": return await client.send_message( mobj.channel, "You didn't search for anything!") msg.replace(" ", "%20") # replace spaces url = "https://duckduckgo.com/html/?q={0}".format(msg) bs = BS(re_get(url).text, "html.parser") results = bs.find_all("div", class_="web-result") if not results: return await client.send_message(mobj.channel, "Couldn't find anything") a = results[0].find("a", class_="result__a") title, link = a.text, a["href"] return await client.send_message(mobj.channel, "{} - {}".format(title, link)) except Exception as ex: logger("Fail: {}".format(ex)) return await client.send_message(mobj.channel, "Failed to get the search")
async def yt(msg, mobj): """ Do a youtube search and yield the first result Example: !yt how do I take a screenshot """ try: if msg == "": return await client.send_message( mobj.channel, "You didn't search for anything!") msg.replace(" ", "+") url = "https://www.youtube.com/results?search_query={}".format(msg) bs = BS(re_get(url).text, "html.parser") items = bs.find("div", id="results").find_all("div", class_="yt-lockup-content") if not items: return await client.send_message(mobj.channel, "Couldn't find any results") # Search for a proper youtube url, has to start with /watch # TODO: rewrite this with a list comp/filter i, found = 0, False while not found and i < 20: href = items[i].find("a", class_="yt-uix-sessionlink")["href"] if href.startswith("/watch"): found = True i += 1 if not found: return await client.send_message(mobj.channel, "Couldn't find a link") return await client.send_message(mobj.channel, "https://youtube.com{}".format(href)) except Exception as ex: logger("Fail: {}".format(ex)) return await client.send_message(mobj.channel, "Failed to request the search")
def get_bs(url): return BeautifulSoup(re_get("{}{}".format(base_url, url)).text, 'html.parser')
async def lastmatch(msg, mobj): """ Fetch a user's ID from the FS and yield the last played match from the OpenDota API The user must first associate a Dota ID with !dota_id to use this """ fname = bot_data(f"{mobj.author.id}.txt") if not fname: return await client.send_message(mobj.channel, "Register your ID first") dota_id = None with open(fname, 'r') as f: dota_id = f.read().strip("\n") r = re_get(f"{OPENDOTA_API}/players/{dota_id}/matches?limit=1") if r.status_code != 200: return await client.send_message(mobj.channel, "Failed to get matches") data = r.json() mid = data[0]['match_id'] mr = re_get(f"{OPENDOTA_API}/matches/{mid}") if mr.status_code != 200: return await client.send_message(mobj.channel, "Error retrieving data") # Find the player object in the players property mdata = mr.json() players = mdata["players"] pfilter = [p for p in players if str(p["account_id"]) == dota_id] if not pfilter: return await client.send_message(mobj.channel, f"Couldn't find user (???)") player = pfilter[0] victory = "won" if player["win"] == 1 else "lost" # Start grabbing details pname = player["personaname"] heroid = player["hero_id"] k = player["kills"] d = player["deaths"] a = player["assists"] kda = player["kda"] gpm = player["gold_per_min"] damage_dealt = player["hero_damage"] team = player["isRadiant"] # t if Rad, f if Dire hero_filter = [h for h in hero_data if h["id"] == heroid] if not hero_filter: return await client.send_message(mobj.channel, f"Can't find hero {heroid}") hero_name = hero_filter[0]["localized_name"] # Grab Ping details of entire team ppings = player["pings"] total_pings = sum([p["pings"] for p in players if p["isRadiant"] == team]) pingpc = round((float(ppings) / total_pings) * 100.0, 2) # Grab bounty runes picked up (bounty is ID# 5) bounties = player["runes"].get("5", 0) all_bounties = sum([p["runes"].get("5", 0) for p in players]) bcp = round((float(bounties) / all_bounties) * 100.0, 2) # Grab messages sent in all chat allchat = mdata["chat"] allchat_msgs = sorted([m for m in allchat if m["unit"] == pname], key=lambda d: len(d["key"]), reverse=True) acp = round((float(len(allchat_msgs)) / len(allchat)) * 100.0, 2) allchat_longest = "" if allchat_msgs: allchat_longest = allchat_msgs[0]['key'] # Get team's kills and calculate kill participation ts = mdata["radiant_score"] if team else mdata["dire_score"] kp = round(float(k + a) / ts, 2) # Create an embed inside of Discord emb = Embed(title=f"Match {mid}", url=f"{OPENDOTA_URL}/{mid}", description=f"{pname} {victory} as **{hero_name}**", color=0x993925) # Set the embed image in the corner # emb.set_thumbnail(url="https://lol.com/lol.jpg") emb.add_field(name="Score", value=f"{k}/{d}/{a} (KDA:{kda}, GPM:{gpm})") if bounties: emb.add_field(name="Bounty Runes Collected", value=f"{bounties} ({bcp}% of all bounties)") if ppings: emb.add_field(name="Ping Stats", value=f"{ppings} ({pingpc}% of team)") if allchat_msgs: emb.add_field(name="Allchat Stats", value=f"{len(allchat_msgs)} ({acp}% of allchat)") emb.add_field(name="Longest Quote", value=f"*'{allchat_longest}'* -{pname}") emb.set_footer(text=f"Provided by OpenDota API") return await client.send_message(mobj.channel, embed=emb)
OPENDOTA_URL = "https://opendota.com/matches" OPENDOTA_API = "https://api.opendota.com/api" # Prefetch a list of heroes from OpenDota # Cache it to disk just to avoid making too many reqs hero_data_cached = False hero_dataf = Path(bot_data("heroes.json")) # Check if the file exists in the system # Else load the JSON from a request if hero_dataf.is_file(): hero_data_cached = True with open(hero_dataf, "r") as f: hero_data = jload(f) else: r = re_get(f"{OPENDOTA_API}/heroes") if r.status_code != 200: print(f"Error pre-fetching hero data (code: {r.status_code})") hero_data_cached = False hero_data = r.json() @register_command async def osfrog(msg, mobj): """ Patch 7.02: help string was removed from Captain's Mode """ osfrogs = [ "Added Monkey King to the game", "Reduced Lone Druid's respawn talent -50s to -40s", ]
def get_url(url): return re_get(url).json()
def get_url(self, url): if self.requests_installed: return re_get(url).json() return json_load(urlopen(url).read().decode('utf-8'))