1
0
Fork 0

Improve denuvo-detection by also checking Steam's DRM notice.

This commit is contained in:
Casper V. Kristensen 2018-08-04 19:37:19 +02:00
parent 4ee7b0e65a
commit 3b993ab811
Signed by: caspervk
GPG key ID: B1156723DB3BDDA8
3 changed files with 49 additions and 41 deletions

View file

@ -175,50 +175,48 @@ class DailyReleasesBot(object):
# If one of the store links 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. # Note: Doesn't apply to Steam bundles, as Steam has no public API for those.
try: if "Steam" in store_links:
steam_type, steam_appid = re.search("(app|sub)(?:/)([0-9]+)", store_links["Steam"]).groups()
logger.debug("Getting information about game using Steam API") logger.debug("Getting information about game using Steam API")
steam_type, steam_appid = re.search("(app|sub|bundle)(?:/)([0-9]+)", store_links["Steam"]).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 == "bundle":
if steam_type == "sub": logger.debug("Steam link is to bundle: not utilizing API")
steam_packagedetails = self.steam.packagedetails(steam_appid)
# Set game name to package name (e.g. 'Fallout New Vegas Ultimate' instead of 'Fallout New Vegas')
game_name = steam_packagedetails["name"]
# Find "base game" of the package; the most popular app (i.e. the one with the most reviews)
steam_package_appids = [str(app["id"]) for app in steam_packagedetails["apps"]]
steam_package_apps_appdetails = [self.steam.appdetails(appid) for appid in steam_package_appids]
steam_package_basegame_appdetails = max(steam_package_apps_appdetails,
key=lambda app: self.steam.reviews(app["steam_appid"]).number)
# Use the base game as the basis for further computation
steam_appdetails = steam_package_basegame_appdetails
steam_appid = steam_package_basegame_appdetails["steam_appid"]
# Otherwise, if the release is a single game on Steam
else: else:
steam_appdetails = self.steam.appdetails(steam_appid) # If the release is a package on Steam (e.g. game + dlc), we need to find the base game of the package
game_name = steam_appdetails["name"] if steam_type == "sub":
steam_packagedetails = self.steam.packagedetails(steam_appid)
# Now that we have a single Steam game to represent the release, use it to improve the information # Set game name to package name (e.g. 'Fallout New Vegas Ultimate' instead of 'Fallout New Vegas')
score, num_reviews = self.steam.reviews(steam_appid) game_name = steam_packagedetails["name"]
# DLC releases doesn't always contain the word "dlc" (e.g. 'Fallout New Vegas: Dead Money'), so some DLCs # Find "base game" of the package; the most popular app (i.e. the one with the most reviews)
# get mislabeled as games during offline parsing. We can use the Steam API to get the correct release type, steam_package_appids = [str(app["id"]) for app in steam_packagedetails["apps"]]
# but if the release was already deemed an update, keep it as such, because an update to a DLC is an update. steam_package_apps_appdetails = [self.steam.appdetails(appid) for appid in steam_package_appids]
if steam_appdetails["type"] == "dlc" and rls_type != "Update": steam_package_basegame_appdetails = max(steam_package_apps_appdetails,
rls_type = "DLC" key=lambda app: self.steam.reviews(app["steam_appid"]).num)
# If Steam links to a 3rd-party EULA, check it for the word "denuvo" and add a highlight if it occurs # Use the base game as the basis for further computation
if "denuvo" in self.steam.eula(steam_appid).lower(): steam_appdetails = steam_package_basegame_appdetails
logger.info("'denuvo' found in EULA; adding 'DENUVO' to highlights") steam_appid = steam_package_basegame_appdetails["steam_appid"]
highlights.append("DENUVO")
except KeyError: # Otherwise, if the release is a single game on Steam
pass # no link to Steam store else:
except AttributeError: steam_appdetails = self.steam.appdetails(steam_appid)
logger.debug("Steam link is to bundle: not utilizing API") game_name = steam_appdetails["name"]
# Now that we have a single Steam game to represent the release, use it to improve the information
score, num_reviews = self.steam.reviews(steam_appid)
# DLC releases don't always contain the word "dlc" (e.g. 'Fallout New Vegas: Dead Money'), so some DLCs
# get mislabeled as games during offline parsing. We can use Steam's API to get the correct type, but if
# the release was already deemed an update, keep it as such, because an update to a DLC is an update.
if steam_appdetails["type"] == "dlc" and rls_type != "Update":
rls_type = "DLC"
# Add highlight if "denuvo" occurs in Steam's DRM notice or potential 3rd-party EULA
if "denuvo" in (steam_appdetails.get("drm_notice", "") + self.steam.eula(steam_appid)).lower():
logger.info("'denuvo' found in Steam DRM-notice/EULA; adding 'DENUVO' to highlights")
highlights.append("DENUVO")
release = { release = {
"dirname": dirname, "dirname": dirname,

View file

@ -1,6 +1,8 @@
import logging import logging
from collections import namedtuple from collections import namedtuple
from bs4 import BeautifulSoup
from dailyreleases import util from dailyreleases import util
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -38,7 +40,7 @@ class Steam(object):
def reviews(self, appid): def reviews(self, appid):
app_review = self.appreviews(appid) app_review = self.appreviews(appid)
Reviews = namedtuple("Reviews", ("score", "number")) Reviews = namedtuple("Reviews", ("score", "num"))
if app_review["total_reviews"] == 0: if app_review["total_reviews"] == 0:
return Reviews(-1, -1) return Reviews(-1, -1)
@ -47,7 +49,11 @@ class Steam(object):
return Reviews(positive, app_review["total_reviews"]) return Reviews(positive, app_review["total_reviews"])
def eula(self, appid): def eula(self, appid):
return self.cache.get(f"https://store.steampowered.com//eula/{appid}_eula_0").text r = self.cache.get(f"https://store.steampowered.com//eula/{appid}_eula_0")
soup = BeautifulSoup(r.text, "html.parser").find(id="eula_content")
if soup is not None:
return soup.text
return ""
def search(self, query): def search(self, query):
logger.debug("Searching Steam store for %s", query) logger.debug("Searching Steam store for %s", query)

View file

@ -113,9 +113,13 @@ class ParseDirnameTestCase(unittest.TestCase):
self.assertEqual("Game", p["type"]) self.assertEqual("Game", p["type"])
self.assertIn("store.steampowered.com/bundle/232", p["store_links"]["Steam"]) self.assertIn("store.steampowered.com/bundle/232", p["store_links"]["Steam"])
def test_denuvo_eula(self): def test_steam_denuvo(self):
# "denuvo" occurs in the Steam EULA
p = self.bot.parse_dirname("Deus.Ex.Mankind.Divided-CPY") p = self.bot.parse_dirname("Deus.Ex.Mankind.Divided-CPY")
self.assertIn("store.steampowered.com/app/337000", p["store_links"]["Steam"]) self.assertEqual(["DENUVO"], p["highlights"])
# "denuvo" occurs in the Steam DRM notice
p = self.bot.parse_dirname("Yakuza.0-FAKE")
self.assertEqual(["DENUVO"], p["highlights"]) self.assertEqual(["DENUVO"], p["highlights"])
def test_episode_release(self): def test_episode_release(self):