prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  isup responds twice
  <!-- Before reporting a bug, please search both open *and closed* issues to
  see if it has already been reported. If you can, try to reproduce the problem
  on an unmodified copy of the `master` branch first, as sometimes bugs are found
  and fixed without a report. If the problem is unreported and persists in
  `master`, please help us fix it quickly by filling out as much of this
  information as you can. Thanks! -->
  
  ### Description
  when I run .isup or .isupinsecure, the bot responds twice. first is the error (if any) then it says that the site is up
  ### Reproduction steps
  1. setup a sopel bot using the master branch.
  2. in the irc channel run .isup with some url that is down
  3. it responds twice
  
  ### Expected behavior
  only responds with an error or else up, not up and error
  
  ### Environment
  - Sopel `.version`: [e.g. 7.0.0 or d416e19] master branch
  - Sopel installed via: [apt, pip, `setup.py install`, source, ?] source
  - Python version: [e.g. 3.6.9] 3.7
  - Operating system: [e.g. Debian 10] debian buster
  - IRCd `/version`: [e.g. InspIRCd 3.0.1] freenode
  - Relevant plugins: [adminchannel, weather, custom\_thing.py, ?] isup
  
  ### Notes
  seems to be because in https://github.com/sopel-irc/sopel/blob/master/sopel/modules/isup.py#L89 none of the except statements return and so the bot.say for "website is up" is always executed.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `sopel/modules/isup.py`
  Content:
  ```
  1 # coding=utf-8
  2 """
  3 isup.py - Sopel Website Status Check Plugin
  4 Copyright 2011, Elsie Powell http://embolalia.com
  5 Licensed under the Eiffel Forum License 2.
  6 
  7 https://sopel.chat
  8 """
  9 from __future__ import absolute_import, division, print_function, unicode_literals
  10 
  11 import requests
  12 
  13 from sopel import plugin
  14 
  15 
  16 PLUGIN_OUTPUT_PREFIX = '[isup] '
  17 
  18 
  19 def get_site_url(site):
  20     """Get a ``site`` URL
  21 
  22     :param str site: the site to get URL for
  23     :return: a valid site URL
  24     :raise ValueError: when site is empty, or isn't well formatted
  25 
  26     The ``site`` argument is checked: its scheme must be ``http`` or ``https``,
  27     or a :exc:`ValueError` is raised.
  28 
  29     If the ``site`` does not have a scheme, ``http`` is used. If it doesn't
  30     have a TLD, a :exc:`ValueError` is raised.
  31     """
  32     site = site.strip() if site else ''
  33     if not site:
  34         raise ValueError('What site do you want to check?')
  35 
  36     if not site.startswith(('http://', 'https://')):
  37         if '://' in site:
  38             protocol = site.split('://')[0] + '://'
  39             raise ValueError('Try it again without the %s' % protocol)
  40 
  41         site = 'http://' + site
  42 
  43     domain = site.split('/')[2].split(':')[0]
  44     if '.' not in domain:
  45         raise ValueError('I need a fully qualified domain name (with a dot).')
  46     if domain.endswith(('.local', '.example', '.test', '.invalid', '.localhost')):
  47         raise ValueError("I can't check LAN-local or invalid domains.")
  48 
  49     return site
  50 
  51 
  52 def handle_isup(bot, trigger, secure=True):
  53     """Handle the ``bot`` command from ``trigger``
  54 
  55     :param bot: Sopel instance
  56     :type bot: :class:`sopel.bot.SopelWrapper`
  57     :param trigger: Command's trigger instance
  58     :type trigger: :class:`sopel.trigger.Trigger`
  59     :param bool secure: Check SSL error if ``True`` (the default)
  60     """
  61     try:
  62         site = get_site_url(trigger.group(2))
  63         response = requests.head(site, verify=secure, timeout=(10.0, 5.0))
  64         response.raise_for_status()
  65     except ValueError as error:
  66         bot.reply(str(error))
  67     except requests.exceptions.SSLError:
  68         bot.say(
  69             '{} looks down to me (SSL error). Try using `{}isupinsecure`.'
  70             .format(site, bot.config.core.help_prefix))
  71     except requests.HTTPError:
  72         bot.say(
  73             '{} looks down to me (HTTP {} "{}").'
  74             .format(site, response.status_code, response.reason))
  75     except requests.ConnectTimeout:
  76         bot.say(
  77             '{} looks down to me (timed out while connecting).'
  78             .format(site))
  79     except requests.ReadTimeout:
  80         bot.say(
  81             '{} looks down to me (timed out waiting for reply).'
  82             .format(site))
  83     except requests.ConnectionError:
  84         bot.say(
  85             '{} looks down to me (connection error).'
  86             .format(site))
  87 
  88     # If no exception happened, the request succeeded.
  89     bot.say(site + ' looks fine to me.')
  90 
  91 
  92 @plugin.command('isupinsecure')
  93 @plugin.output_prefix(PLUGIN_OUTPUT_PREFIX)
  94 def isup_insecure(bot, trigger):
  95     """Check if a website is up (without verifying HTTPS)."""
  96     handle_isup(bot, trigger, secure=False)
  97 
  98 
  99 @plugin.command('isup')
  100 @plugin.example('.isup google.com',
  101                 'http://google.com looks fine to me.',
  102                 online=True, vcr=True)
  103 @plugin.output_prefix(PLUGIN_OUTPUT_PREFIX)
  104 def isup(bot, trigger):
  105     """Check if a website is up or not."""
  106     handle_isup(bot, trigger, secure=True)
  107
  ```
  --- 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/sopel/modules/isup.py b/sopel/modules/isup.py
  --- a/sopel/modules/isup.py
  +++ b/sopel/modules/isup.py
  @@ -84,9 +84,9 @@
           bot.say(
               '{} looks down to me (connection error).'
               .format(site))
  -
  -    # If no exception happened, the request succeeded.
  -    bot.say(site + ' looks fine to me.')
  +    else:
  +        # If no exception happened, the request must have succeeded.
  +        bot.say(site + ' looks fine to me.')
   
   
   @plugin.command('isupinsecure')
  @@ -97,9 +97,7 @@
   
   
   @plugin.command('isup')
  -@plugin.example('.isup google.com',
  -                'http://google.com looks fine to me.',
  -                online=True, vcr=True)
  +@plugin.example('.isup google.com')
   @plugin.output_prefix(PLUGIN_OUTPUT_PREFIX)
   def isup(bot, trigger):
       """Check if a website is up or not."""
  
verification_info: {"golden_diff": "diff --git a/sopel/modules/isup.py b/sopel/modules/isup.py\n--- a/sopel/modules/isup.py\n+++ b/sopel/modules/isup.py\n@@ -84,9 +84,9 @@\n         bot.say(\n             '{} looks down to me (connection error).'\n             .format(site))\n-\n-    # If no exception happened, the request succeeded.\n-    bot.say(site + ' looks fine to me.')\n+    else:\n+        # If no exception happened, the request must have succeeded.\n+        bot.say(site + ' looks fine to me.')\n \n \n @plugin.command('isupinsecure')\n@@ -97,9 +97,7 @@\n \n \n @plugin.command('isup')\n-@plugin.example('.isup google.com',\n-                'http://google.com looks fine to me.',\n-                online=True, vcr=True)\n+@plugin.example('.isup google.com')\n @plugin.output_prefix(PLUGIN_OUTPUT_PREFIX)\n def isup(bot, trigger):\n     \"\"\"Check if a website is up or not.\"\"\"\n", "issue": "isup responds twice\n<!-- Before reporting a bug, please search both open *and closed* issues to\r\nsee if it has already been reported. If you can, try to reproduce the problem\r\non an unmodified copy of the `master` branch first, as sometimes bugs are found\r\nand fixed without a report. If the problem is unreported and persists in\r\n`master`, please help us fix it quickly by filling out as much of this\r\ninformation as you can. Thanks! -->\r\n\r\n### Description\r\nwhen I run .isup or .isupinsecure, the bot responds twice. first is the error (if any) then it says that the site is up\r\n### Reproduction steps\r\n1. setup a sopel bot using the master branch.\r\n2. in the irc channel run .isup with some url that is down\r\n3. it responds twice\r\n\r\n### Expected behavior\r\nonly responds with an error or else up, not up and error\r\n\r\n### Environment\r\n- Sopel `.version`: [e.g. 7.0.0 or d416e19] master branch\r\n- Sopel installed via: [apt, pip, `setup.py install`, source, ?] source\r\n- Python version: [e.g. 3.6.9] 3.7\r\n- Operating system: [e.g. Debian 10] debian buster\r\n- IRCd `/version`: [e.g. InspIRCd 3.0.1] freenode\r\n- Relevant plugins: [adminchannel, weather, custom\\_thing.py, ?] isup\r\n\r\n### Notes\r\nseems to be because in https://github.com/sopel-irc/sopel/blob/master/sopel/modules/isup.py#L89 none of the except statements return and so the bot.say for \"website is up\" is always executed.\r\n\n", "before_files": [{"content": "# coding=utf-8\n\"\"\"\nisup.py - Sopel Website Status Check Plugin\nCopyright 2011, Elsie Powell http://embolalia.com\nLicensed under the Eiffel Forum License 2.\n\nhttps://sopel.chat\n\"\"\"\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport requests\n\nfrom sopel import plugin\n\n\nPLUGIN_OUTPUT_PREFIX = '[isup] '\n\n\ndef get_site_url(site):\n    \"\"\"Get a ``site`` URL\n\n    :param str site: the site to get URL for\n    :return: a valid site URL\n    :raise ValueError: when site is empty, or isn't well formatted\n\n    The ``site`` argument is checked: its scheme must be ``http`` or ``https``,\n    or a :exc:`ValueError` is raised.\n\n    If the ``site`` does not have a scheme, ``http`` is used. If it doesn't\n    have a TLD, a :exc:`ValueError` is raised.\n    \"\"\"\n    site = site.strip() if site else ''\n    if not site:\n        raise ValueError('What site do you want to check?')\n\n    if not site.startswith(('http://', 'https://')):\n        if '://' in site:\n            protocol = site.split('://')[0] + '://'\n            raise ValueError('Try it again without the %s' % protocol)\n\n        site = 'http://' + site\n\n    domain = site.split('/')[2].split(':')[0]\n    if '.' not in domain:\n        raise ValueError('I need a fully qualified domain name (with a dot).')\n    if domain.endswith(('.local', '.example', '.test', '.invalid', '.localhost')):\n        raise ValueError(\"I can't check LAN-local or invalid domains.\")\n\n    return site\n\n\ndef handle_isup(bot, trigger, secure=True):\n    \"\"\"Handle the ``bot`` command from ``trigger``\n\n    :param bot: Sopel instance\n    :type bot: :class:`sopel.bot.SopelWrapper`\n    :param trigger: Command's trigger instance\n    :type trigger: :class:`sopel.trigger.Trigger`\n    :param bool secure: Check SSL error if ``True`` (the default)\n    \"\"\"\n    try:\n        site = get_site_url(trigger.group(2))\n        response = requests.head(site, verify=secure, timeout=(10.0, 5.0))\n        response.raise_for_status()\n    except ValueError as error:\n        bot.reply(str(error))\n    except requests.exceptions.SSLError:\n        bot.say(\n            '{} looks down to me (SSL error). Try using `{}isupinsecure`.'\n            .format(site, bot.config.core.help_prefix))\n    except requests.HTTPError:\n        bot.say(\n            '{} looks down to me (HTTP {} \"{}\").'\n            .format(site, response.status_code, response.reason))\n    except requests.ConnectTimeout:\n        bot.say(\n            '{} looks down to me (timed out while connecting).'\n            .format(site))\n    except requests.ReadTimeout:\n        bot.say(\n            '{} looks down to me (timed out waiting for reply).'\n            .format(site))\n    except requests.ConnectionError:\n        bot.say(\n            '{} looks down to me (connection error).'\n            .format(site))\n\n    # If no exception happened, the request succeeded.\n    bot.say(site + ' looks fine to me.')\n\n\n@plugin.command('isupinsecure')\n@plugin.output_prefix(PLUGIN_OUTPUT_PREFIX)\ndef isup_insecure(bot, trigger):\n    \"\"\"Check if a website is up (without verifying HTTPS).\"\"\"\n    handle_isup(bot, trigger, secure=False)\n\n\n@plugin.command('isup')\n@plugin.example('.isup google.com',\n                'http://google.com looks fine to me.',\n                online=True, vcr=True)\n@plugin.output_prefix(PLUGIN_OUTPUT_PREFIX)\ndef isup(bot, trigger):\n    \"\"\"Check if a website is up or not.\"\"\"\n    handle_isup(bot, trigger, secure=True)\n", "path": "sopel/modules/isup.py"}], "after_files": [{"content": "# coding=utf-8\n\"\"\"\nisup.py - Sopel Website Status Check Plugin\nCopyright 2011, Elsie Powell http://embolalia.com\nLicensed under the Eiffel Forum License 2.\n\nhttps://sopel.chat\n\"\"\"\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport requests\n\nfrom sopel import plugin\n\n\nPLUGIN_OUTPUT_PREFIX = '[isup] '\n\n\ndef get_site_url(site):\n    \"\"\"Get a ``site`` URL\n\n    :param str site: the site to get URL for\n    :return: a valid site URL\n    :raise ValueError: when site is empty, or isn't well formatted\n\n    The ``site`` argument is checked: its scheme must be ``http`` or ``https``,\n    or a :exc:`ValueError` is raised.\n\n    If the ``site`` does not have a scheme, ``http`` is used. If it doesn't\n    have a TLD, a :exc:`ValueError` is raised.\n    \"\"\"\n    site = site.strip() if site else ''\n    if not site:\n        raise ValueError('What site do you want to check?')\n\n    if not site.startswith(('http://', 'https://')):\n        if '://' in site:\n            protocol = site.split('://')[0] + '://'\n            raise ValueError('Try it again without the %s' % protocol)\n\n        site = 'http://' + site\n\n    domain = site.split('/')[2].split(':')[0]\n    if '.' not in domain:\n        raise ValueError('I need a fully qualified domain name (with a dot).')\n    if domain.endswith(('.local', '.example', '.test', '.invalid', '.localhost')):\n        raise ValueError(\"I can't check LAN-local or invalid domains.\")\n\n    return site\n\n\ndef handle_isup(bot, trigger, secure=True):\n    \"\"\"Handle the ``bot`` command from ``trigger``\n\n    :param bot: Sopel instance\n    :type bot: :class:`sopel.bot.SopelWrapper`\n    :param trigger: Command's trigger instance\n    :type trigger: :class:`sopel.trigger.Trigger`\n    :param bool secure: Check SSL error if ``True`` (the default)\n    \"\"\"\n    try:\n        site = get_site_url(trigger.group(2))\n        response = requests.head(site, verify=secure, timeout=(10.0, 5.0))\n        response.raise_for_status()\n    except ValueError as error:\n        bot.reply(str(error))\n    except requests.exceptions.SSLError:\n        bot.say(\n            '{} looks down to me (SSL error). Try using `{}isupinsecure`.'\n            .format(site, bot.config.core.help_prefix))\n    except requests.HTTPError:\n        bot.say(\n            '{} looks down to me (HTTP {} \"{}\").'\n            .format(site, response.status_code, response.reason))\n    except requests.ConnectTimeout:\n        bot.say(\n            '{} looks down to me (timed out while connecting).'\n            .format(site))\n    except requests.ReadTimeout:\n        bot.say(\n            '{} looks down to me (timed out waiting for reply).'\n            .format(site))\n    except requests.ConnectionError:\n        bot.say(\n            '{} looks down to me (connection error).'\n            .format(site))\n    else:\n        # If no exception happened, the request must have succeeded.\n        bot.say(site + ' looks fine to me.')\n\n\n@plugin.command('isupinsecure')\n@plugin.output_prefix(PLUGIN_OUTPUT_PREFIX)\ndef isup_insecure(bot, trigger):\n    \"\"\"Check if a website is up (without verifying HTTPS).\"\"\"\n    handle_isup(bot, trigger, secure=False)\n\n\n@plugin.command('isup')\n@plugin.example('.isup google.com')\n@plugin.output_prefix(PLUGIN_OUTPUT_PREFIX)\ndef isup(bot, trigger):\n    \"\"\"Check if a website is up or not.\"\"\"\n    handle_isup(bot, trigger, secure=True)\n", "path": "sopel/modules/isup.py"}]}