prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Create desktop/application menu shortcut writes a bad .desktop file
  File contents:
  
  ```
  [Desktop Entry]
  Type=Application
  Name=%s
  Icon=%s
  Exec=lutris lutris:%s
  Categories=Game
  ```
  
  **How to reproduce**
  Right click a game and select Create desktop shortcut.
  Navigate to ~/Desktop
  You see a file with name `gameslug-id.desktop` but it contains what's above. If you're in a file manager you see the game title instead of the filename, so it appears as `%s` there.
  
  **Lutris debug output**
  
  ```
  [system]:Executing which xdg-user-dir
  ```
  
  Operating system: Arch Linux
  
  
  --- 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/shortcuts.py`
  Content:
  ```
  1 """Desktop file creator."""
  2 import os
  3 import stat
  4 import shutil
  5 import subprocess
  6 
  7 from textwrap import dedent
  8 from xdg import BaseDirectory
  9 from gi.repository import GLib
  10 
  11 from lutris.util import system
  12 from lutris.util.log import logger
  13 from lutris.settings import CACHE_DIR
  14 
  15 
  16 def get_xdg_basename(game_slug, game_id, legacy=False):
  17     if legacy:
  18         filename = "{}.desktop".format(game_slug)
  19     else:
  20         filename = "{}-{}.desktop".format(game_slug, game_id)
  21     return filename
  22 
  23 
  24 def create_launcher(game_slug, game_id, game_name, desktop=False, menu=False):
  25     """Create a .desktop file."""
  26     desktop_dir = (
  27         GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP)
  28     )
  29     launcher_content = dedent(
  30         """
  31         [Desktop Entry]
  32         Type=Application
  33         Name=%s
  34         Icon=%s
  35         Exec=lutris lutris:%s
  36         Categories=Game
  37         """.format(game_name, 'lutris_{}'.format(game_slug), game_id)
  38     )
  39 
  40     launcher_filename = get_xdg_basename(game_slug, game_id, legacy=False)
  41     tmp_launcher_path = os.path.join(CACHE_DIR, launcher_filename)
  42     tmp_launcher = open(tmp_launcher_path,  "w")
  43     tmp_launcher.write(launcher_content)
  44     tmp_launcher.close()
  45     os.chmod(tmp_launcher_path, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC |
  46              stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP)
  47 
  48     if desktop:
  49         shutil.copy(tmp_launcher_path,
  50                     os.path.join(desktop_dir, launcher_filename))
  51     if menu:
  52         menu_path = os.path.join(GLib.get_user_data_dir(), 'applications')
  53         shutil.copy(tmp_launcher_path,
  54                     os.path.join(menu_path, launcher_filename))
  55     os.remove(tmp_launcher_path)
  56 
  57 
  58 def get_launcher_path(game_slug, game_id):
  59     """Return the path of a XDG game launcher.
  60     When legacy is set, it will return the old path with only the slug,
  61     otherwise it will return the path with slug + id
  62     """
  63     xdg_executable = 'xdg-user-dir'
  64     if not system.find_executable(xdg_executable):
  65         logger.error("%s not found", xdg_executable)
  66         return
  67     desktop_dir = subprocess.Popen([xdg_executable, 'DESKTOP'],
  68                                    stdout=subprocess.PIPE).communicate()[0]
  69     desktop_dir = str(desktop_dir).strip()
  70 
  71     legacy_launcher_path = os.path.join(
  72         desktop_dir, get_xdg_basename(game_slug, game_id, legacy=True)
  73     )
  74     # First check if legacy path exists, for backward compatibility
  75     if system.path_exists(legacy_launcher_path):
  76         return legacy_launcher_path
  77     # Otherwise return new path, whether it exists or not
  78     return os.path.join(
  79         desktop_dir, get_xdg_basename(game_slug, game_id, legacy=False)
  80     )
  81 
  82 
  83 def get_menu_launcher_path(game_slug, game_id):
  84     """Return the path to a XDG menu launcher, prioritizing legacy paths if
  85     they exist
  86     """
  87     menu_dir = os.path.join(BaseDirectory.xdg_data_home, 'applications')
  88     menu_path = os.path.join(
  89         menu_dir, get_xdg_basename(game_slug, game_id, legacy=True)
  90     )
  91     if system.path_exists(menu_path):
  92         return menu_path
  93     return os.path.join(
  94         menu_dir, get_xdg_basename(game_slug, game_id, legacy=False)
  95     )
  96 
  97 
  98 def desktop_launcher_exists(game_slug, game_id):
  99     return system.path_exists(get_launcher_path(game_slug, game_id))
  100 
  101 
  102 def menu_launcher_exists(game_slug, game_id):
  103     return system.path_exists(get_menu_launcher_path(game_slug, game_id))
  104 
  105 
  106 def remove_launcher(game_slug, game_id, desktop=False, menu=False):
  107     """Remove existing .desktop file."""
  108     if desktop:
  109         launcher_path = get_launcher_path(game_slug, game_id)
  110         if system.path_exists(launcher_path):
  111             os.remove(launcher_path)
  112 
  113     if menu:
  114         menu_path = get_menu_launcher_path(game_slug, game_id)
  115         if system.path_exists(menu_path):
  116             os.remove(menu_path)
  117
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/lutris/shortcuts.py b/lutris/shortcuts.py
  --- a/lutris/shortcuts.py
  +++ b/lutris/shortcuts.py
  @@ -30,9 +30,9 @@
           """
           [Desktop Entry]
           Type=Application
  -        Name=%s
  -        Icon=%s
  -        Exec=lutris lutris:%s
  +        Name={}
  +        Icon={}
  +        Exec=lutris lutris:{}
           Categories=Game
           """.format(game_name, 'lutris_{}'.format(game_slug), game_id)
       )
  
verification_info: {"golden_diff": "diff --git a/lutris/shortcuts.py b/lutris/shortcuts.py\n--- a/lutris/shortcuts.py\n+++ b/lutris/shortcuts.py\n@@ -30,9 +30,9 @@\n         \"\"\"\n         [Desktop Entry]\n         Type=Application\n-        Name=%s\n-        Icon=%s\n-        Exec=lutris lutris:%s\n+        Name={}\n+        Icon={}\n+        Exec=lutris lutris:{}\n         Categories=Game\n         \"\"\".format(game_name, 'lutris_{}'.format(game_slug), game_id)\n     )\n", "issue": "Create desktop/application menu shortcut writes a bad .desktop file\nFile contents:\n\n```\n[Desktop Entry]\nType=Application\nName=%s\nIcon=%s\nExec=lutris lutris:%s\nCategories=Game\n```\n\n**How to reproduce**\nRight click a game and select Create desktop shortcut.\nNavigate to ~/Desktop\nYou see a file with name `gameslug-id.desktop` but it contains what's above. If you're in a file manager you see the game title instead of the filename, so it appears as `%s` there.\n\n**Lutris debug output**\n\n```\n[system]:Executing which xdg-user-dir\n```\n\nOperating system: Arch Linux\n\n", "before_files": [{"content": "\"\"\"Desktop file creator.\"\"\"\nimport os\nimport stat\nimport shutil\nimport subprocess\n\nfrom textwrap import dedent\nfrom xdg import BaseDirectory\nfrom gi.repository import GLib\n\nfrom lutris.util import system\nfrom lutris.util.log import logger\nfrom lutris.settings import CACHE_DIR\n\n\ndef get_xdg_basename(game_slug, game_id, legacy=False):\n    if legacy:\n        filename = \"{}.desktop\".format(game_slug)\n    else:\n        filename = \"{}-{}.desktop\".format(game_slug, game_id)\n    return filename\n\n\ndef create_launcher(game_slug, game_id, game_name, desktop=False, menu=False):\n    \"\"\"Create a .desktop file.\"\"\"\n    desktop_dir = (\n        GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP)\n    )\n    launcher_content = dedent(\n        \"\"\"\n        [Desktop Entry]\n        Type=Application\n        Name=%s\n        Icon=%s\n        Exec=lutris lutris:%s\n        Categories=Game\n        \"\"\".format(game_name, 'lutris_{}'.format(game_slug), game_id)\n    )\n\n    launcher_filename = get_xdg_basename(game_slug, game_id, legacy=False)\n    tmp_launcher_path = os.path.join(CACHE_DIR, launcher_filename)\n    tmp_launcher = open(tmp_launcher_path,  \"w\")\n    tmp_launcher.write(launcher_content)\n    tmp_launcher.close()\n    os.chmod(tmp_launcher_path, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC |\n             stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP)\n\n    if desktop:\n        shutil.copy(tmp_launcher_path,\n                    os.path.join(desktop_dir, launcher_filename))\n    if menu:\n        menu_path = os.path.join(GLib.get_user_data_dir(), 'applications')\n        shutil.copy(tmp_launcher_path,\n                    os.path.join(menu_path, launcher_filename))\n    os.remove(tmp_launcher_path)\n\n\ndef get_launcher_path(game_slug, game_id):\n    \"\"\"Return the path of a XDG game launcher.\n    When legacy is set, it will return the old path with only the slug,\n    otherwise it will return the path with slug + id\n    \"\"\"\n    xdg_executable = 'xdg-user-dir'\n    if not system.find_executable(xdg_executable):\n        logger.error(\"%s not found\", xdg_executable)\n        return\n    desktop_dir = subprocess.Popen([xdg_executable, 'DESKTOP'],\n                                   stdout=subprocess.PIPE).communicate()[0]\n    desktop_dir = str(desktop_dir).strip()\n\n    legacy_launcher_path = os.path.join(\n        desktop_dir, get_xdg_basename(game_slug, game_id, legacy=True)\n    )\n    # First check if legacy path exists, for backward compatibility\n    if system.path_exists(legacy_launcher_path):\n        return legacy_launcher_path\n    # Otherwise return new path, whether it exists or not\n    return os.path.join(\n        desktop_dir, get_xdg_basename(game_slug, game_id, legacy=False)\n    )\n\n\ndef get_menu_launcher_path(game_slug, game_id):\n    \"\"\"Return the path to a XDG menu launcher, prioritizing legacy paths if\n    they exist\n    \"\"\"\n    menu_dir = os.path.join(BaseDirectory.xdg_data_home, 'applications')\n    menu_path = os.path.join(\n        menu_dir, get_xdg_basename(game_slug, game_id, legacy=True)\n    )\n    if system.path_exists(menu_path):\n        return menu_path\n    return os.path.join(\n        menu_dir, get_xdg_basename(game_slug, game_id, legacy=False)\n    )\n\n\ndef desktop_launcher_exists(game_slug, game_id):\n    return system.path_exists(get_launcher_path(game_slug, game_id))\n\n\ndef menu_launcher_exists(game_slug, game_id):\n    return system.path_exists(get_menu_launcher_path(game_slug, game_id))\n\n\ndef remove_launcher(game_slug, game_id, desktop=False, menu=False):\n    \"\"\"Remove existing .desktop file.\"\"\"\n    if desktop:\n        launcher_path = get_launcher_path(game_slug, game_id)\n        if system.path_exists(launcher_path):\n            os.remove(launcher_path)\n\n    if menu:\n        menu_path = get_menu_launcher_path(game_slug, game_id)\n        if system.path_exists(menu_path):\n            os.remove(menu_path)\n", "path": "lutris/shortcuts.py"}], "after_files": [{"content": "\"\"\"Desktop file creator.\"\"\"\nimport os\nimport stat\nimport shutil\nimport subprocess\n\nfrom textwrap import dedent\nfrom xdg import BaseDirectory\nfrom gi.repository import GLib\n\nfrom lutris.util import system\nfrom lutris.util.log import logger\nfrom lutris.settings import CACHE_DIR\n\n\ndef get_xdg_basename(game_slug, game_id, legacy=False):\n    if legacy:\n        filename = \"{}.desktop\".format(game_slug)\n    else:\n        filename = \"{}-{}.desktop\".format(game_slug, game_id)\n    return filename\n\n\ndef create_launcher(game_slug, game_id, game_name, desktop=False, menu=False):\n    \"\"\"Create a .desktop file.\"\"\"\n    desktop_dir = (\n        GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP)\n    )\n    launcher_content = dedent(\n        \"\"\"\n        [Desktop Entry]\n        Type=Application\n        Name={}\n        Icon={}\n        Exec=lutris lutris:{}\n        Categories=Game\n        \"\"\".format(game_name, 'lutris_{}'.format(game_slug), game_id)\n    )\n\n    launcher_filename = get_xdg_basename(game_slug, game_id, legacy=False)\n    tmp_launcher_path = os.path.join(CACHE_DIR, launcher_filename)\n    tmp_launcher = open(tmp_launcher_path,  \"w\")\n    tmp_launcher.write(launcher_content)\n    tmp_launcher.close()\n    os.chmod(tmp_launcher_path, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC |\n             stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP)\n\n    if desktop:\n        shutil.copy(tmp_launcher_path,\n                    os.path.join(desktop_dir, launcher_filename))\n    if menu:\n        menu_path = os.path.join(GLib.get_user_data_dir(), 'applications')\n        shutil.copy(tmp_launcher_path,\n                    os.path.join(menu_path, launcher_filename))\n    os.remove(tmp_launcher_path)\n\n\ndef get_launcher_path(game_slug, game_id):\n    \"\"\"Return the path of a XDG game launcher.\n    When legacy is set, it will return the old path with only the slug,\n    otherwise it will return the path with slug + id\n    \"\"\"\n    xdg_executable = 'xdg-user-dir'\n    if not system.find_executable(xdg_executable):\n        logger.error(\"%s not found\", xdg_executable)\n        return\n    desktop_dir = subprocess.Popen([xdg_executable, 'DESKTOP'],\n                                   stdout=subprocess.PIPE).communicate()[0]\n    desktop_dir = str(desktop_dir).strip()\n\n    legacy_launcher_path = os.path.join(\n        desktop_dir, get_xdg_basename(game_slug, game_id, legacy=True)\n    )\n    # First check if legacy path exists, for backward compatibility\n    if system.path_exists(legacy_launcher_path):\n        return legacy_launcher_path\n    # Otherwise return new path, whether it exists or not\n    return os.path.join(\n        desktop_dir, get_xdg_basename(game_slug, game_id, legacy=False)\n    )\n\n\ndef get_menu_launcher_path(game_slug, game_id):\n    \"\"\"Return the path to a XDG menu launcher, prioritizing legacy paths if\n    they exist\n    \"\"\"\n    menu_dir = os.path.join(BaseDirectory.xdg_data_home, 'applications')\n    menu_path = os.path.join(\n        menu_dir, get_xdg_basename(game_slug, game_id, legacy=True)\n    )\n    if system.path_exists(menu_path):\n        return menu_path\n    return os.path.join(\n        menu_dir, get_xdg_basename(game_slug, game_id, legacy=False)\n    )\n\n\ndef desktop_launcher_exists(game_slug, game_id):\n    return system.path_exists(get_launcher_path(game_slug, game_id))\n\n\ndef menu_launcher_exists(game_slug, game_id):\n    return system.path_exists(get_menu_launcher_path(game_slug, game_id))\n\n\ndef remove_launcher(game_slug, game_id, desktop=False, menu=False):\n    \"\"\"Remove existing .desktop file.\"\"\"\n    if desktop:\n        launcher_path = get_launcher_path(game_slug, game_id)\n        if system.path_exists(launcher_path):\n            os.remove(launcher_path)\n\n    if menu:\n        menu_path = get_menu_launcher_path(game_slug, game_id)\n        if system.path_exists(menu_path):\n            os.remove(menu_path)\n", "path": "lutris/shortcuts.py"}]}