We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Game Sync Bug (Proton,Steamworks Banner etc.)
If you ever install a Winesteam Game or use Steam Play with Proton from the beta branch, Lutris scan some necessary Steam Applications and show it as Gamebanner:

![auswahl_001](https://user-images.githubusercontent.com/22080674/44949553-645aba00-ae34-11e8-932c-bbad2f16c833.png)

this happen cause the Application have a SteamID:

in this case:
Proton 3.7 Beta: 930400
Proton 3.7: 858280

(also Steamworks SDK from Wine-Steam have a ID, but i dont have it installed atm)

As a User, we can "delete" it via the Context Menu from the Lutris Main Window but it dont work permanent, cause after a restart it get again synced and shown.

Pls to fix :+1: 





--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lutris/services/steam.py`
Content:
```
1 import os
2 import re
3 from collections import defaultdict
4 
5 from lutris import pga
6 from lutris.util.log import logger
7 from lutris.util.steam import vdf_parse
8 from lutris.util.system import fix_path_case
9 from lutris.util.strings import slugify
10 from lutris.config import make_game_config_id, LutrisConfig
11 
12 NAME = 'Steam'
13 
14 APP_STATE_FLAGS = [
15     "Invalid",
16     "Uninstalled",
17     "Update Required",
18     "Fully Installed",
19     "Encrypted",
20     "Locked",
21     "Files Missing",
22     "AppRunning",
23     "Files Corrupt",
24     "Update Running",
25     "Update Paused",
26     "Update Started",
27     "Uninstalling",
28     "Backup Running",
29     "Reconfiguring",
30     "Validating",
31     "Adding Files",
32     "Preallocating",
33     "Downloading",
34     "Staging",
35     "Committing",
36     "Update Stopping"
37 ]
38 
39 
40 class AppManifest:
41     def __init__(self, appmanifest_path):
42         self.appmanifest_path = appmanifest_path
43         self.steamapps_path, filename = os.path.split(appmanifest_path)
44         self.steamid = re.findall(r'(\d+)', filename)[-1]
45         if os.path.exists(appmanifest_path):
46             with open(appmanifest_path, "r") as appmanifest_file:
47                 self.appmanifest_data = vdf_parse(appmanifest_file, {})
48 
49     def __repr__(self):
50         return "<AppManifest: %s>" % self.appmanifest_path
51 
52     @property
53     def app_state(self):
54         return self.appmanifest_data.get('AppState') or {}
55 
56     @property
57     def user_config(self):
58         return self.app_state.get('UserConfig') or {}
59 
60     @property
61     def name(self):
62         _name = self.app_state.get('name')
63         if not _name:
64             _name = self.user_config.get('name')
65         return _name
66 
67     @property
68     def slug(self):
69         return slugify(self.name)
70 
71     @property
72     def installdir(self):
73         return self.app_state.get('installdir')
74 
75     @property
76     def states(self):
77         """Return the states of a Steam game."""
78         states = []
79         state_flags = self.app_state.get('StateFlags', 0)
80         state_flags = bin(int(state_flags))[:1:-1]
81         for index, flag in enumerate(state_flags):
82             if flag == '1':
83                 states.append(APP_STATE_FLAGS[index + 1])
84         return states
85 
86     def is_installed(self):
87         return 'Fully Installed' in self.states
88 
89     def get_install_path(self):
90         if not self.installdir:
91             return
92         install_path = fix_path_case(os.path.join(self.steamapps_path, "common",
93                                                   self.installdir))
94         if install_path:
95             return install_path
96 
97     def get_platform(self):
98         steamapps_paths = get_steamapps_paths()
99         if self.steamapps_path in steamapps_paths['linux']:
100             return 'linux'
101         elif self.steamapps_path in steamapps_paths['windows']:
102             return 'windows'
103         else:
104             raise ValueError("Can't find %s in %s"
105                              % (self.steamapps_path, steamapps_paths))
106 
107     def get_runner_name(self):
108         platform = self.get_platform()
109         if platform == 'linux':
110             return 'steam'
111         else:
112             return 'winesteam'
113 
114 
115 def get_appmanifests(steamapps_path):
116     """Return the list for all appmanifest files in a Steam library folder"""
117     return [f for f in os.listdir(steamapps_path)
118             if re.match(r'^appmanifest_\d+.acf$', f)]
119 
120 
121 def get_steamapps_paths_for_platform(platform_name):
122     from lutris.runners import winesteam, steam
123     runners = {
124         'linux': steam.steam,
125         'windows': winesteam.winesteam
126     }
127     runner = runners[platform_name]()
128     return runner.get_steamapps_dirs()
129 
130 
131 def get_steamapps_paths(flat=False, platform=None):
132     base_platforms = ['linux', 'windows']
133     if flat:
134         steamapps_paths = []
135     else:
136         steamapps_paths = defaultdict(list)
137 
138     if platform:
139         if platform not in base_platforms:
140             raise ValueError("Illegal value for Steam platform: %s" % platform)
141         platforms = [platform]
142     else:
143         platforms = base_platforms
144 
145     for platform in platforms:
146         folders = get_steamapps_paths_for_platform(platform)
147         if flat:
148             steamapps_paths += folders
149         else:
150             steamapps_paths[platform] = folders
151 
152     return steamapps_paths
153 
154 
155 def get_appmanifest_from_appid(steamapps_path, appid):
156     """Given the steam apps path and appid, return the corresponding appmanifest"""
157     if not steamapps_path:
158         raise ValueError("steamapps_path is mandatory")
159     if not os.path.exists(steamapps_path):
160         raise IOError("steamapps_path must be a valid directory")
161     if not appid:
162         raise ValueError("Missing mandatory appid")
163     appmanifest_path = os.path.join(steamapps_path, "appmanifest_%s.acf" % appid)
164     if not os.path.exists(appmanifest_path):
165         return
166     return AppManifest(appmanifest_path)
167 
168 
169 def get_path_from_appmanifest(steamapps_path, appid):
170     """Return the path where a Steam game is installed."""
171     appmanifest = get_appmanifest_from_appid(steamapps_path, appid)
172     if not appmanifest:
173         return
174     return appmanifest.get_install_path()
175 
176 
177 def mark_as_installed(steamid, runner_name, game_info):
178     for key in ['name', 'slug']:
179         assert game_info[key]
180     logger.info("Setting %s as installed" % game_info['name'])
181     config_id = (game_info.get('config_path') or make_game_config_id(game_info['slug']))
182     game_id = pga.add_or_update(
183         steamid=int(steamid),
184         name=game_info['name'],
185         runner=runner_name,
186         slug=game_info['slug'],
187         installed=1,
188         configpath=config_id,
189     )
190 
191     game_config = LutrisConfig(
192         runner_slug=runner_name,
193         game_config_id=config_id,
194     )
195     game_config.raw_game_config.update({'appid': steamid})
196     game_config.save()
197     return game_id
198 
199 
200 def mark_as_uninstalled(game_info):
201     for key in ('id', 'name'):
202         if key not in game_info:
203             raise ValueError("Missing %s field in %s" % (key, game_info))
204     logger.info('Setting %s as uninstalled' % game_info['name'])
205     game_id = pga.add_or_update(
206         id=game_info['id'],
207         runner='',
208         installed=0
209     )
210     return game_id
211 
212 
213 def sync_appmanifest_state(appmanifest_path, name=None, slug=None):
214     try:
215         appmanifest = AppManifest(appmanifest_path)
216     except Exception:
217         logger.error("Unable to parse file %s", appmanifest_path)
218         return
219     if appmanifest.is_installed():
220         game_info = {
221             'name': name or appmanifest.name,
222             'slug': slug or appmanifest.slug,
223         }
224         runner_name = appmanifest.get_runner_name()
225         mark_as_installed(appmanifest.steamid, runner_name, game_info)
226 
227 
228 def sync_with_lutris(platform='linux'):
229     steamapps_paths = get_steamapps_paths()
230     steam_games_in_lutris = pga.get_games_where(steamid__isnull=False, steamid__not='')
231     steamids_in_lutris = set([str(game['steamid']) for game in steam_games_in_lutris])
232     seen_ids = set()  # Set of Steam appids seen while browsing AppManifests
233 
234     for steamapps_path in steamapps_paths[platform]:
235         appmanifests = get_appmanifests(steamapps_path)
236         for appmanifest_file in appmanifests:
237             steamid = re.findall(r'(\d+)', appmanifest_file)[0]
238             seen_ids.add(steamid)
239             appmanifest_path = os.path.join(steamapps_path, appmanifest_file)
240             if steamid not in steamids_in_lutris:
241                 # New Steam game, not seen before in Lutris,
242                 if platform != 'linux':
243                     # Windows games might require additional steps.
244                     # TODO: Find a way to mark games as "Not fully configured"
245                     # as the status.
246                     logger.warning("Importing Steam game %s but game might require additional configuration")
247                 sync_appmanifest_state(appmanifest_path)
248             else:
249                 # Lookup previously installed Steam games
250                 pga_entry = None
251                 for game in steam_games_in_lutris:
252                     if str(game['steamid']) == steamid and not game['installed']:
253                         pga_entry = game
254                         break
255                 if pga_entry:
256                     sync_appmanifest_state(appmanifest_path, name=pga_entry['name'], slug=pga_entry['slug'])
257     unavailable_ids = steamids_in_lutris.difference(seen_ids)
258     for steamid in unavailable_ids:
259         for game in steam_games_in_lutris:
260             runner = 'steam' if platform == 'linux' else 'winesteam'
261             if str(game['steamid']) == steamid \
262                and game['installed'] \
263                and game['runner'] == runner:
264                 mark_as_uninstalled(game)
265
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lutris/services/steam.py b/lutris/services/steam.py
--- a/lutris/services/steam.py
+++ b/lutris/services/steam.py
@@ -228,6 +228,7 @@
 def sync_with_lutris(platform='linux'):
     steamapps_paths = get_steamapps_paths()
     steam_games_in_lutris = pga.get_games_where(steamid__isnull=False, steamid__not='')
+    proton_ids = ["858280", "930400"]
     steamids_in_lutris = set([str(game['steamid']) for game in steam_games_in_lutris])
     seen_ids = set()  # Set of Steam appids seen while browsing AppManifests
 
@@ -237,7 +238,7 @@
             steamid = re.findall(r'(\d+)', appmanifest_file)[0]
             seen_ids.add(steamid)
             appmanifest_path = os.path.join(steamapps_path, appmanifest_file)
-            if steamid not in steamids_in_lutris:
+            if steamid not in steamids_in_lutris and steamid not in proton_ids:
                 # New Steam game, not seen before in Lutris,
                 if platform != 'linux':
                     # Windows games might require additional steps.

{"golden_diff": "diff --git a/lutris/services/steam.py b/lutris/services/steam.py\n--- a/lutris/services/steam.py\n+++ b/lutris/services/steam.py\n@@ -228,6 +228,7 @@\n def sync_with_lutris(platform='linux'):\n     steamapps_paths = get_steamapps_paths()\n     steam_games_in_lutris = pga.get_games_where(steamid__isnull=False, steamid__not='')\n+    proton_ids = [\"858280\", \"930400\"]\n     steamids_in_lutris = set([str(game['steamid']) for game in steam_games_in_lutris])\n     seen_ids = set()  # Set of Steam appids seen while browsing AppManifests\n \n@@ -237,7 +238,7 @@\n             steamid = re.findall(r'(\\d+)', appmanifest_file)[0]\n             seen_ids.add(steamid)\n             appmanifest_path = os.path.join(steamapps_path, appmanifest_file)\n-            if steamid not in steamids_in_lutris:\n+            if steamid not in steamids_in_lutris and steamid not in proton_ids:\n                 # New Steam game, not seen before in Lutris,\n                 if platform != 'linux':\n                     # Windows games might require additional steps.\n", "issue": "Game Sync Bug (Proton,Steamworks Banner etc.)\nIf you ever install a Winesteam Game or use Steam Play with Proton from the beta branch, Lutris scan some necessary Steam Applications and show it as Gamebanner:\r\n\r\n![auswahl_001](https://user-images.githubusercontent.com/22080674/44949553-645aba00-ae34-11e8-932c-bbad2f16c833.png)\r\n\r\nthis happen cause the Application have a SteamID:\r\n\r\nin this case:\r\nProton 3.7 Beta: 930400\r\nProton 3.7: 858280\r\n\r\n(also Steamworks SDK from Wine-Steam have a ID, but i dont have it installed atm)\r\n\r\nAs a User, we can \"delete\" it via the Context Menu from the Lutris Main Window but it dont work permanent, cause after a restart it get again synced and shown.\r\n\r\nPls to fix :+1: \r\n\r\n\r\n\r\n\n", "before_files": [{"content": "import os\nimport re\nfrom collections import defaultdict\n\nfrom lutris import pga\nfrom lutris.util.log import logger\nfrom lutris.util.steam import vdf_parse\nfrom lutris.util.system import fix_path_case\nfrom lutris.util.strings import slugify\nfrom lutris.config import make_game_config_id, LutrisConfig\n\nNAME = 'Steam'\n\nAPP_STATE_FLAGS = [\n    \"Invalid\",\n    \"Uninstalled\",\n    \"Update Required\",\n    \"Fully Installed\",\n    \"Encrypted\",\n    \"Locked\",\n    \"Files Missing\",\n    \"AppRunning\",\n    \"Files Corrupt\",\n    \"Update Running\",\n    \"Update Paused\",\n    \"Update Started\",\n    \"Uninstalling\",\n    \"Backup Running\",\n    \"Reconfiguring\",\n    \"Validating\",\n    \"Adding Files\",\n    \"Preallocating\",\n    \"Downloading\",\n    \"Staging\",\n    \"Committing\",\n    \"Update Stopping\"\n]\n\n\nclass AppManifest:\n    def __init__(self, appmanifest_path):\n        self.appmanifest_path = appmanifest_path\n        self.steamapps_path, filename = os.path.split(appmanifest_path)\n        self.steamid = re.findall(r'(\\d+)', filename)[-1]\n        if os.path.exists(appmanifest_path):\n            with open(appmanifest_path, \"r\") as appmanifest_file:\n                self.appmanifest_data = vdf_parse(appmanifest_file, {})\n\n    def __repr__(self):\n        return \"<AppManifest: %s>\" % self.appmanifest_path\n\n    @property\n    def app_state(self):\n        return self.appmanifest_data.get('AppState') or {}\n\n    @property\n    def user_config(self):\n        return self.app_state.get('UserConfig') or {}\n\n    @property\n    def name(self):\n        _name = self.app_state.get('name')\n        if not _name:\n            _name = self.user_config.get('name')\n        return _name\n\n    @property\n    def slug(self):\n        return slugify(self.name)\n\n    @property\n    def installdir(self):\n        return self.app_state.get('installdir')\n\n    @property\n    def states(self):\n        \"\"\"Return the states of a Steam game.\"\"\"\n        states = []\n        state_flags = self.app_state.get('StateFlags', 0)\n        state_flags = bin(int(state_flags))[:1:-1]\n        for index, flag in enumerate(state_flags):\n            if flag == '1':\n                states.append(APP_STATE_FLAGS[index + 1])\n        return states\n\n    def is_installed(self):\n        return 'Fully Installed' in self.states\n\n    def get_install_path(self):\n        if not self.installdir:\n            return\n        install_path = fix_path_case(os.path.join(self.steamapps_path, \"common\",\n                                                  self.installdir))\n        if install_path:\n            return install_path\n\n    def get_platform(self):\n        steamapps_paths = get_steamapps_paths()\n        if self.steamapps_path in steamapps_paths['linux']:\n            return 'linux'\n        elif self.steamapps_path in steamapps_paths['windows']:\n            return 'windows'\n        else:\n            raise ValueError(\"Can't find %s in %s\"\n                             % (self.steamapps_path, steamapps_paths))\n\n    def get_runner_name(self):\n        platform = self.get_platform()\n        if platform == 'linux':\n            return 'steam'\n        else:\n            return 'winesteam'\n\n\ndef get_appmanifests(steamapps_path):\n    \"\"\"Return the list for all appmanifest files in a Steam library folder\"\"\"\n    return [f for f in os.listdir(steamapps_path)\n            if re.match(r'^appmanifest_\\d+.acf$', f)]\n\n\ndef get_steamapps_paths_for_platform(platform_name):\n    from lutris.runners import winesteam, steam\n    runners = {\n        'linux': steam.steam,\n        'windows': winesteam.winesteam\n    }\n    runner = runners[platform_name]()\n    return runner.get_steamapps_dirs()\n\n\ndef get_steamapps_paths(flat=False, platform=None):\n    base_platforms = ['linux', 'windows']\n    if flat:\n        steamapps_paths = []\n    else:\n        steamapps_paths = defaultdict(list)\n\n    if platform:\n        if platform not in base_platforms:\n            raise ValueError(\"Illegal value for Steam platform: %s\" % platform)\n        platforms = [platform]\n    else:\n        platforms = base_platforms\n\n    for platform in platforms:\n        folders = get_steamapps_paths_for_platform(platform)\n        if flat:\n            steamapps_paths += folders\n        else:\n            steamapps_paths[platform] = folders\n\n    return steamapps_paths\n\n\ndef get_appmanifest_from_appid(steamapps_path, appid):\n    \"\"\"Given the steam apps path and appid, return the corresponding appmanifest\"\"\"\n    if not steamapps_path:\n        raise ValueError(\"steamapps_path is mandatory\")\n    if not os.path.exists(steamapps_path):\n        raise IOError(\"steamapps_path must be a valid directory\")\n    if not appid:\n        raise ValueError(\"Missing mandatory appid\")\n    appmanifest_path = os.path.join(steamapps_path, \"appmanifest_%s.acf\" % appid)\n    if not os.path.exists(appmanifest_path):\n        return\n    return AppManifest(appmanifest_path)\n\n\ndef get_path_from_appmanifest(steamapps_path, appid):\n    \"\"\"Return the path where a Steam game is installed.\"\"\"\n    appmanifest = get_appmanifest_from_appid(steamapps_path, appid)\n    if not appmanifest:\n        return\n    return appmanifest.get_install_path()\n\n\ndef mark_as_installed(steamid, runner_name, game_info):\n    for key in ['name', 'slug']:\n        assert game_info[key]\n    logger.info(\"Setting %s as installed\" % game_info['name'])\n    config_id = (game_info.get('config_path') or make_game_config_id(game_info['slug']))\n    game_id = pga.add_or_update(\n        steamid=int(steamid),\n        name=game_info['name'],\n        runner=runner_name,\n        slug=game_info['slug'],\n        installed=1,\n        configpath=config_id,\n    )\n\n    game_config = LutrisConfig(\n        runner_slug=runner_name,\n        game_config_id=config_id,\n    )\n    game_config.raw_game_config.update({'appid': steamid})\n    game_config.save()\n    return game_id\n\n\ndef mark_as_uninstalled(game_info):\n    for key in ('id', 'name'):\n        if key not in game_info:\n            raise ValueError(\"Missing %s field in %s\" % (key, game_info))\n    logger.info('Setting %s as uninstalled' % game_info['name'])\n    game_id = pga.add_or_update(\n        id=game_info['id'],\n        runner='',\n        installed=0\n    )\n    return game_id\n\n\ndef sync_appmanifest_state(appmanifest_path, name=None, slug=None):\n    try:\n        appmanifest = AppManifest(appmanifest_path)\n    except Exception:\n        logger.error(\"Unable to parse file %s\", appmanifest_path)\n        return\n    if appmanifest.is_installed():\n        game_info = {\n            'name': name or appmanifest.name,\n            'slug': slug or appmanifest.slug,\n        }\n        runner_name = appmanifest.get_runner_name()\n        mark_as_installed(appmanifest.steamid, runner_name, game_info)\n\n\ndef sync_with_lutris(platform='linux'):\n    steamapps_paths = get_steamapps_paths()\n    steam_games_in_lutris = pga.get_games_where(steamid__isnull=False, steamid__not='')\n    steamids_in_lutris = set([str(game['steamid']) for game in steam_games_in_lutris])\n    seen_ids = set()  # Set of Steam appids seen while browsing AppManifests\n\n    for steamapps_path in steamapps_paths[platform]:\n        appmanifests = get_appmanifests(steamapps_path)\n        for appmanifest_file in appmanifests:\n            steamid = re.findall(r'(\\d+)', appmanifest_file)[0]\n            seen_ids.add(steamid)\n            appmanifest_path = os.path.join(steamapps_path, appmanifest_file)\n            if steamid not in steamids_in_lutris:\n                # New Steam game, not seen before in Lutris,\n                if platform != 'linux':\n                    # Windows games might require additional steps.\n                    # TODO: Find a way to mark games as \"Not fully configured\"\n                    # as the status.\n                    logger.warning(\"Importing Steam game %s but game might require additional configuration\")\n                sync_appmanifest_state(appmanifest_path)\n            else:\n                # Lookup previously installed Steam games\n                pga_entry = None\n                for game in steam_games_in_lutris:\n                    if str(game['steamid']) == steamid and not game['installed']:\n                        pga_entry = game\n                        break\n                if pga_entry:\n                    sync_appmanifest_state(appmanifest_path, name=pga_entry['name'], slug=pga_entry['slug'])\n    unavailable_ids = steamids_in_lutris.difference(seen_ids)\n    for steamid in unavailable_ids:\n        for game in steam_games_in_lutris:\n            runner = 'steam' if platform == 'linux' else 'winesteam'\n            if str(game['steamid']) == steamid \\\n               and game['installed'] \\\n               and game['runner'] == runner:\n                mark_as_uninstalled(game)\n", "path": "lutris/services/steam.py"}], "after_files": [{"content": "import os\nimport re\nfrom collections import defaultdict\n\nfrom lutris import pga\nfrom lutris.util.log import logger\nfrom lutris.util.steam import vdf_parse\nfrom lutris.util.system import fix_path_case\nfrom lutris.util.strings import slugify\nfrom lutris.config import make_game_config_id, LutrisConfig\n\nNAME = 'Steam'\n\nAPP_STATE_FLAGS = [\n    \"Invalid\",\n    \"Uninstalled\",\n    \"Update Required\",\n    \"Fully Installed\",\n    \"Encrypted\",\n    \"Locked\",\n    \"Files Missing\",\n    \"AppRunning\",\n    \"Files Corrupt\",\n    \"Update Running\",\n    \"Update Paused\",\n    \"Update Started\",\n    \"Uninstalling\",\n    \"Backup Running\",\n    \"Reconfiguring\",\n    \"Validating\",\n    \"Adding Files\",\n    \"Preallocating\",\n    \"Downloading\",\n    \"Staging\",\n    \"Committing\",\n    \"Update Stopping\"\n]\n\n\nclass AppManifest:\n    def __init__(self, appmanifest_path):\n        self.appmanifest_path = appmanifest_path\n        self.steamapps_path, filename = os.path.split(appmanifest_path)\n        self.steamid = re.findall(r'(\\d+)', filename)[-1]\n        if os.path.exists(appmanifest_path):\n            with open(appmanifest_path, \"r\") as appmanifest_file:\n                self.appmanifest_data = vdf_parse(appmanifest_file, {})\n\n    def __repr__(self):\n        return \"<AppManifest: %s>\" % self.appmanifest_path\n\n    @property\n    def app_state(self):\n        return self.appmanifest_data.get('AppState') or {}\n\n    @property\n    def user_config(self):\n        return self.app_state.get('UserConfig') or {}\n\n    @property\n    def name(self):\n        _name = self.app_state.get('name')\n        if not _name:\n            _name = self.user_config.get('name')\n        return _name\n\n    @property\n    def slug(self):\n        return slugify(self.name)\n\n    @property\n    def installdir(self):\n        return self.app_state.get('installdir')\n\n    @property\n    def states(self):\n        \"\"\"Return the states of a Steam game.\"\"\"\n        states = []\n        state_flags = self.app_state.get('StateFlags', 0)\n        state_flags = bin(int(state_flags))[:1:-1]\n        for index, flag in enumerate(state_flags):\n            if flag == '1':\n                states.append(APP_STATE_FLAGS[index + 1])\n        return states\n\n    def is_installed(self):\n        return 'Fully Installed' in self.states\n\n    def get_install_path(self):\n        if not self.installdir:\n            return\n        install_path = fix_path_case(os.path.join(self.steamapps_path, \"common\",\n                                                  self.installdir))\n        if install_path:\n            return install_path\n\n    def get_platform(self):\n        steamapps_paths = get_steamapps_paths()\n        if self.steamapps_path in steamapps_paths['linux']:\n            return 'linux'\n        elif self.steamapps_path in steamapps_paths['windows']:\n            return 'windows'\n        else:\n            raise ValueError(\"Can't find %s in %s\"\n                             % (self.steamapps_path, steamapps_paths))\n\n    def get_runner_name(self):\n        platform = self.get_platform()\n        if platform == 'linux':\n            return 'steam'\n        else:\n            return 'winesteam'\n\n\ndef get_appmanifests(steamapps_path):\n    \"\"\"Return the list for all appmanifest files in a Steam library folder\"\"\"\n    return [f for f in os.listdir(steamapps_path)\n            if re.match(r'^appmanifest_\\d+.acf$', f)]\n\n\ndef get_steamapps_paths_for_platform(platform_name):\n    from lutris.runners import winesteam, steam\n    runners = {\n        'linux': steam.steam,\n        'windows': winesteam.winesteam\n    }\n    runner = runners[platform_name]()\n    return runner.get_steamapps_dirs()\n\n\ndef get_steamapps_paths(flat=False, platform=None):\n    base_platforms = ['linux', 'windows']\n    if flat:\n        steamapps_paths = []\n    else:\n        steamapps_paths = defaultdict(list)\n\n    if platform:\n        if platform not in base_platforms:\n            raise ValueError(\"Illegal value for Steam platform: %s\" % platform)\n        platforms = [platform]\n    else:\n        platforms = base_platforms\n\n    for platform in platforms:\n        folders = get_steamapps_paths_for_platform(platform)\n        if flat:\n            steamapps_paths += folders\n        else:\n            steamapps_paths[platform] = folders\n\n    return steamapps_paths\n\n\ndef get_appmanifest_from_appid(steamapps_path, appid):\n    \"\"\"Given the steam apps path and appid, return the corresponding appmanifest\"\"\"\n    if not steamapps_path:\n        raise ValueError(\"steamapps_path is mandatory\")\n    if not os.path.exists(steamapps_path):\n        raise IOError(\"steamapps_path must be a valid directory\")\n    if not appid:\n        raise ValueError(\"Missing mandatory appid\")\n    appmanifest_path = os.path.join(steamapps_path, \"appmanifest_%s.acf\" % appid)\n    if not os.path.exists(appmanifest_path):\n        return\n    return AppManifest(appmanifest_path)\n\n\ndef get_path_from_appmanifest(steamapps_path, appid):\n    \"\"\"Return the path where a Steam game is installed.\"\"\"\n    appmanifest = get_appmanifest_from_appid(steamapps_path, appid)\n    if not appmanifest:\n        return\n    return appmanifest.get_install_path()\n\n\ndef mark_as_installed(steamid, runner_name, game_info):\n    for key in ['name', 'slug']:\n        assert game_info[key]\n    logger.info(\"Setting %s as installed\" % game_info['name'])\n    config_id = (game_info.get('config_path') or make_game_config_id(game_info['slug']))\n    game_id = pga.add_or_update(\n        steamid=int(steamid),\n        name=game_info['name'],\n        runner=runner_name,\n        slug=game_info['slug'],\n        installed=1,\n        configpath=config_id,\n    )\n\n    game_config = LutrisConfig(\n        runner_slug=runner_name,\n        game_config_id=config_id,\n    )\n    game_config.raw_game_config.update({'appid': steamid})\n    game_config.save()\n    return game_id\n\n\ndef mark_as_uninstalled(game_info):\n    for key in ('id', 'name'):\n        if key not in game_info:\n            raise ValueError(\"Missing %s field in %s\" % (key, game_info))\n    logger.info('Setting %s as uninstalled' % game_info['name'])\n    game_id = pga.add_or_update(\n        id=game_info['id'],\n        runner='',\n        installed=0\n    )\n    return game_id\n\n\ndef sync_appmanifest_state(appmanifest_path, name=None, slug=None):\n    try:\n        appmanifest = AppManifest(appmanifest_path)\n    except Exception:\n        logger.error(\"Unable to parse file %s\", appmanifest_path)\n        return\n    if appmanifest.is_installed():\n        game_info = {\n            'name': name or appmanifest.name,\n            'slug': slug or appmanifest.slug,\n        }\n        runner_name = appmanifest.get_runner_name()\n        mark_as_installed(appmanifest.steamid, runner_name, game_info)\n\n\ndef sync_with_lutris(platform='linux'):\n    steamapps_paths = get_steamapps_paths()\n    steam_games_in_lutris = pga.get_games_where(steamid__isnull=False, steamid__not='')\n    proton_ids = [\"858280\", \"930400\"]\n    steamids_in_lutris = set([str(game['steamid']) for game in steam_games_in_lutris])\n    seen_ids = set()  # Set of Steam appids seen while browsing AppManifests\n\n    for steamapps_path in steamapps_paths[platform]:\n        appmanifests = get_appmanifests(steamapps_path)\n        for appmanifest_file in appmanifests:\n            steamid = re.findall(r'(\\d+)', appmanifest_file)[0]\n            seen_ids.add(steamid)\n            appmanifest_path = os.path.join(steamapps_path, appmanifest_file)\n            if steamid not in steamids_in_lutris and steamid not in proton_ids:\n                # New Steam game, not seen before in Lutris,\n                if platform != 'linux':\n                    # Windows games might require additional steps.\n                    # TODO: Find a way to mark games as \"Not fully configured\"\n                    # as the status.\n                    logger.warning(\"Importing Steam game %s but game might require additional configuration\")\n                sync_appmanifest_state(appmanifest_path)\n            else:\n                # Lookup previously installed Steam games\n                pga_entry = None\n                for game in steam_games_in_lutris:\n                    if str(game['steamid']) == steamid and not game['installed']:\n                        pga_entry = game\n                        break\n                if pga_entry:\n                    sync_appmanifest_state(appmanifest_path, name=pga_entry['name'], slug=pga_entry['slug'])\n    unavailable_ids = steamids_in_lutris.difference(seen_ids)\n    for steamid in unavailable_ids:\n        for game in steam_games_in_lutris:\n            runner = 'steam' if platform == 'linux' else 'winesteam'\n            if str(game['steamid']) == steamid \\\n               and game['installed'] \\\n               and game['runner'] == runner:\n                mark_as_uninstalled(game)\n", "path": "lutris/services/steam.py"}]}