Add support for multiple store links.
This commit is contained in:
parent
1fc385e440
commit
e62e608c48
|
@ -4,7 +4,7 @@ import logging
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Gog(object):
|
||||
class GOG(object):
|
||||
def __init__(self, cache) -> None:
|
||||
self.cache = cache
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import requests_cache
|
|||
from tabulate import tabulate
|
||||
|
||||
from dailyreleases import config, __version__
|
||||
from dailyreleases.gog import GOG
|
||||
from dailyreleases.predb import Predb
|
||||
from dailyreleases.reddit import Reddit
|
||||
from dailyreleases.steam import Steam
|
||||
|
@ -39,6 +40,7 @@ class DailyReleasesBot(object):
|
|||
self.web = Web(self.config, self.cache)
|
||||
self.predb = Predb(self.cache)
|
||||
self.steam = Steam(self.cache)
|
||||
self.gog = GOG(self.cache)
|
||||
self.reddit = Reddit(self.config)
|
||||
|
||||
def run(self):
|
||||
|
@ -70,21 +72,25 @@ class DailyReleasesBot(object):
|
|||
print("Exiting (KeyboardInterrupt)")
|
||||
break
|
||||
|
||||
def find_store_link(self, game_name):
|
||||
"""
|
||||
Try to find hyperlink to a store selling this game.
|
||||
def find_store_links(self, game_name) -> dict:
|
||||
links = {}
|
||||
|
||||
:return: (Link, name of store)
|
||||
"""
|
||||
# Try searching the Steam store for the game
|
||||
link = self.steam.search(game_name)
|
||||
if link:
|
||||
return link, "Steam"
|
||||
# Steam
|
||||
steam_link = self.steam.search(game_name)
|
||||
if steam_link:
|
||||
links["Steam"] = steam_link
|
||||
|
||||
# If that didn't work, try Googling the game
|
||||
# GOG
|
||||
gog_link = self.gog.search(game_name)
|
||||
if gog_link:
|
||||
links["GOG"] = f"{gog_link} 'DRM-Free! 👍'" # hover text
|
||||
|
||||
if links:
|
||||
return links
|
||||
|
||||
# If none of those worked, try Googling the game
|
||||
known_stores = {
|
||||
"store.steampowered.com/(app|sub)": "Steam", # order doesn't matter
|
||||
"store.steampowered.com/bundle": "Steam Bundle",
|
||||
"store.steampowered.com/(app|sub|bundle)": "Steam", # order doesn't matter
|
||||
"gog.com/game": "GOG",
|
||||
"origin.com": "Origin",
|
||||
"ubi(soft)?.com": "Ubisoft",
|
||||
|
@ -99,10 +105,10 @@ class DailyReleasesBot(object):
|
|||
for link in self.web.search(f"{game_name} buy"):
|
||||
for store_url, store_name in known_stores.items():
|
||||
if re.search(store_url, link, flags=re.IGNORECASE):
|
||||
return link, store_name
|
||||
return {store_name: link}
|
||||
|
||||
logger.debug("Unable to find store link for %s", game_name)
|
||||
return None, None
|
||||
logger.debug("Unable to find store links for %s", game_name)
|
||||
return {}
|
||||
|
||||
def parse_dirname(self, dirname):
|
||||
logger.info("---")
|
||||
|
@ -156,11 +162,11 @@ class DailyReleasesBot(object):
|
|||
logger.info("Offline: %s %s : %s - %s", platform, rls_type, game_name, group)
|
||||
logger.info("Tags: %s. Highlights: %s", tags, highlights)
|
||||
|
||||
# Find store link
|
||||
store_link, store_name = self.find_store_link(game_name)
|
||||
# Find store links
|
||||
store_links = self.find_store_links(game_name)
|
||||
|
||||
# No store link? Probably software and not a game
|
||||
if not store_link:
|
||||
if not store_links:
|
||||
logger.info("Skipping %s: no store link (probably software)", dirname)
|
||||
return
|
||||
|
||||
|
@ -169,11 +175,11 @@ class DailyReleasesBot(object):
|
|||
popularity = -1
|
||||
review_score = -1
|
||||
|
||||
# If the store link we found is to Steam, use their API to get (better) information about the game.
|
||||
# If one of the store links we found is to Steam, use their API to get (better) information about the game.
|
||||
# Note: Doesn't apply to Steam bundles, as Steam has no public API for those.
|
||||
if store_name == "Steam":
|
||||
try:
|
||||
steam_type, steam_appid = re.search("(app|sub)(?:/)([0-9]+)", store_links["Steam"]).groups()
|
||||
logger.debug("Getting information about game using Steam API")
|
||||
steam_type, steam_appid = re.search("(app|sub)(?:/)([0-9]+)", store_link).groups()
|
||||
|
||||
# If the release is a package on Steam (e.g. game + dlc), we need to find the base game of the package
|
||||
if steam_type == "sub":
|
||||
|
@ -212,9 +218,10 @@ class DailyReleasesBot(object):
|
|||
logger.info("'denuvo' found in EULA; adding 'DENUVO' to highlights")
|
||||
highlights.append("DENUVO")
|
||||
|
||||
# We only called it "Steam Bundle" to bypass the Steam-API logic. Fix for aesthetics.
|
||||
if store_name == "Steam Bundle":
|
||||
store_name = "Steam"
|
||||
except KeyError:
|
||||
pass # no link to Steam store
|
||||
except AttributeError:
|
||||
logger.debug("Steam link is to bundle: not utilizing API")
|
||||
|
||||
release = {
|
||||
"dirname": dirname,
|
||||
|
@ -223,8 +230,7 @@ class DailyReleasesBot(object):
|
|||
"game_name": game_name,
|
||||
"type": rls_type,
|
||||
"platform": platform,
|
||||
"store_link": store_link,
|
||||
"store_name": store_name,
|
||||
"store_links": store_links,
|
||||
"popularity": popularity,
|
||||
"review_score": review_score,
|
||||
"tags": tags,
|
||||
|
@ -309,13 +315,13 @@ class DailyReleasesBot(object):
|
|||
name = "[{}{}]({}){}".format(r["game_name"], tags, r["nfo_link"], highlights)
|
||||
|
||||
if r["review_score"] != -1:
|
||||
review_score = "{:.0%} ^^\({}\)".format(r["review_score"], r["popularity"])
|
||||
reviews = "{:.0%} ^^\({}\)".format(r["review_score"], r["popularity"])
|
||||
else:
|
||||
review_score = "-"
|
||||
reviews = "-"
|
||||
|
||||
store = "[{}]({})".format(r["store_name"], r["store_link"])
|
||||
stores = ", ".join(f"[{name}]({link})" for name, link in r["store_links"].items())
|
||||
|
||||
return name, r["group"], review_score, store
|
||||
return name, r["group"], reviews, stores
|
||||
|
||||
# Releases in the sub-tables are grouped by release group, and the groups are ordered according to the
|
||||
# most popular game within the group. Games are sorted by popularity internally in the groups.
|
||||
|
@ -327,7 +333,7 @@ class DailyReleasesBot(object):
|
|||
for rls in sorted(type_releases,
|
||||
key=lambda r: (group_popularity[r["group"]], r["group"], r["popularity"]),
|
||||
reverse=True)]
|
||||
post.append(tabulate(table, headers=(type_name, "Group", "Score", "Store"), tablefmt="pipe"))
|
||||
post.append(tabulate(table, headers=(type_name, "Group", "Reviews", "Stores"), tablefmt="pipe"))
|
||||
|
||||
post.append("")
|
||||
post.append(" ")
|
||||
|
|
|
@ -16,8 +16,7 @@ class ParseDirnameTestCase(unittest.TestCase):
|
|||
self.assertEqual("Windows", p["platform"])
|
||||
self.assertEqual("Games", p["type"])
|
||||
self.assertEqual("DARKSiDERS", p["group"])
|
||||
self.assertIn("store.steampowered.com/app/244750", p["store_link"])
|
||||
self.assertEqual("Steam", p["store_name"])
|
||||
self.assertIn("store.steampowered.com/app/244750", p["store_links"]["Steam"])
|
||||
self.assertEqual([], p["tags"])
|
||||
self.assertEqual([], p["highlights"])
|
||||
|
||||
|
@ -56,7 +55,7 @@ class ParseDirnameTestCase(unittest.TestCase):
|
|||
def test_dlc_implicit(self):
|
||||
p = self.bot.parse_dirname("Euro.Truck.Simulator.2.Italia-CODEX")
|
||||
self.assertEqual("DLC", p["type"])
|
||||
self.assertIn("store.steampowered.com/app/558244", p["store_link"])
|
||||
self.assertIn("store.steampowered.com/app/558244", p["store_links"]["Steam"])
|
||||
|
||||
def test_incl_dlc_update(self):
|
||||
p = self.bot.parse_dirname("Wolfenstein.II.The.New.Colossus.Update.5.incl.DLC-CODEX")
|
||||
|
@ -73,14 +72,12 @@ class ParseDirnameTestCase(unittest.TestCase):
|
|||
|
||||
def test_non_steam(self):
|
||||
p = self.bot.parse_dirname("Battlefield.1.REPACK-CPY")
|
||||
self.assertIn("www.origin.com/usa/en-us/store/battlefield/battlefield-1", p["store_link"])
|
||||
self.assertEqual("Origin", p["store_name"])
|
||||
self.assertIn("www.origin.com/usa/en-us/store/battlefield/battlefield-1", p["store_links"]["Origin"])
|
||||
self.assertEqual(-1, p["popularity"])
|
||||
|
||||
def test_gog_exclusive(self):
|
||||
p = self.bot.parse_dirname("Dungeons.and.Dragons.Dragonshard.v2.0.0.10.Multilingual-DELiGHT")
|
||||
self.assertIn("gog.com/game/dungeons_dragons_dragonshard", p["store_link"])
|
||||
self.assertEqual("GOG", p["store_name"])
|
||||
self.assertIn("gog.com/game/dungeons_dragons_dragonshard", p["store_links"]["GOG"])
|
||||
self.assertEqual(-1, p["popularity"])
|
||||
|
||||
def test_popularity_non_steam(self):
|
||||
|
@ -99,14 +96,13 @@ class ParseDirnameTestCase(unittest.TestCase):
|
|||
p = self.bot.parse_dirname("Farming.Simulator.17.Platinum.Edition.Update.v1.5.3-BAT")
|
||||
self.assertEqual("Farming Simulator 17 - Platinum Edition", p["game_name"])
|
||||
self.assertEqual("Updates", p["type"])
|
||||
self.assertIn("store.steampowered.com/sub/202103", p["store_link"])
|
||||
self.assertEqual("Steam", p["store_name"])
|
||||
self.assertIn("store.steampowered.com/sub/202103", p["store_links"]["Steam"])
|
||||
|
||||
def test_steam_package_with_dlc_first(self):
|
||||
p = self.bot.parse_dirname("The.Witcher.3.Wild.Hunt.Game.of.The.Year.Edition-RELOADED")
|
||||
self.assertEqual("The Witcher 3: Wild Hunt - Game of the Year Edition", p["game_name"])
|
||||
self.assertEqual("Games", p["type"])
|
||||
self.assertIn("store.steampowered.com/sub/124923", p["store_link"])
|
||||
self.assertIn("store.steampowered.com/sub/124923", p["store_links"]["Steam"])
|
||||
|
||||
def test_steam_bundle(self):
|
||||
p = self.bot.parse_dirname("Valve.Complete.Pack-FAKE")
|
||||
|
@ -114,18 +110,18 @@ class ParseDirnameTestCase(unittest.TestCase):
|
|||
self.assertEqual("Valve Complete Pack", p["game_name"])
|
||||
self.assertEqual("Windows", p["platform"])
|
||||
self.assertEqual("Games", p["type"])
|
||||
self.assertIn("store.steampowered.com/bundle/232", p["store_link"])
|
||||
self.assertIn("store.steampowered.com/bundle/232", p["store_links"]["Steam"])
|
||||
|
||||
def test_denuvo_eula(self):
|
||||
p = self.bot.parse_dirname("Deus.Ex.Mankind.Divided-CPY")
|
||||
self.assertIn("store.steampowered.com/app/337000", p["store_link"])
|
||||
self.assertIn("store.steampowered.com/app/337000", p["store_links"]["Steam"])
|
||||
self.assertEqual(["DENUVO"], p["highlights"])
|
||||
|
||||
def test_episode_release(self):
|
||||
p = self.bot.parse_dirname("Life.is.Strange.Before.the.Storm.Episode.3-CODEX")
|
||||
self.assertEqual("Life is Strange: Before the Storm Episode 3", p["game_name"])
|
||||
self.assertEqual("DLC", p["type"])
|
||||
self.assertIn("store.steampowered.com/app/704740", p["store_link"])
|
||||
self.assertIn("store.steampowered.com/app/704740", p["store_links"]["Steam"])
|
||||
|
||||
def test_season_and_episode_release(self):
|
||||
p = self.bot.parse_dirname("Minecraft.Story.Mode.Season.Two.Episode.5.MacOSX-RELOADED")
|
||||
|
@ -137,7 +133,7 @@ class ParseDirnameTestCase(unittest.TestCase):
|
|||
|
||||
def test_readnfo_microsoft_store(self):
|
||||
p = self.bot.parse_dirname("Zoo.Tycoon.Ultimate.Animal.Collection.READNFO-CODEX")
|
||||
self.assertIn("microsoft.com/en-us/p/zoo-tycoon-ultimate-animal-collection", p["store_link"])
|
||||
self.assertIn("microsoft.com/en-us/p/zoo-tycoon-ultimate-animal-collection", p["store_links"]["Microsoft Store"])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Reference in a new issue