Repository: sopel-irc/sopel

Issue:
Anonymous gists are going away. Help module will break.
GitHub [announced](https://blog.github.com/2018-02-18-deprecation-notice-removing-anonymous-gist-creation/) last month that anonymous gist creation will be disabled on March 19, 2018 (UTC).

The `help` module was modified in fa89eb7 to essentially paste its output to a gist and simply return the link, and this functionality will break (as of writing) tomorrow. `.help` (or `.commands`) will return an error until (and unless) the module is updated to paste its contents elsewhere and/or create a static HTML file instead as I originally proposed in #1080.

(As an aside, I've been meaning to implement that HTML mode for ages. Maybe this is the kick I needed to finally get off my arse and write it. We'll see.)


Discussion:

Resolving patch:
diff --git a/sopel/modules/help.py b/sopel/modules/help.py
--- a/sopel/modules/help.py
+++ b/sopel/modules/help.py
@@ -3,6 +3,7 @@
 help.py - Sopel Help Module
 Copyright 2008, Sean B. Palmer, inamidst.com
 Copyright © 2013, Elad Alfassa, <elad@fedoraproject.org>
+Copyright © 2018, Adam Erdman, pandorah.org
 Licensed under the Eiffel Forum License 2.
 
 http://sopel.chat
@@ -11,8 +12,6 @@
 
 import textwrap
 import collections
-import json
-
 import requests
 
 from sopel.logger import get_logger
@@ -51,8 +50,8 @@ def help(bot, trigger):
         # actually creating the list first. Maybe worth storing the link and a
         # heuristic in config, too, so it persists across restarts. Would need a
         # command to regenerate, too...
-        if 'command-gist' in bot.memory and bot.memory['command-gist'][0] == len(bot.command_groups):
-            url = bot.memory['command-gist'][1]
+        if 'command-list' in bot.memory and bot.memory['command-list'][0] == len(bot.command_groups):
+            url = bot.memory['command-list'][1]
         else:
             bot.say("Hang on, I'm creating a list.")
             msgs = []
@@ -60,49 +59,39 @@ def help(bot, trigger):
             name_length = max(6, max(len(k) for k in bot.command_groups.keys()))
             for category, cmds in collections.OrderedDict(sorted(bot.command_groups.items())).items():
                 category = category.upper().ljust(name_length)
+                cmds = set(cmds)  # remove duplicates
                 cmds = '  '.join(cmds)
                 msg = category + '  ' + cmds
                 indent = ' ' * (name_length + 2)
                 # Honestly not sure why this is a list here
                 msgs.append('\n'.join(textwrap.wrap(msg, subsequent_indent=indent)))
 
-            url = create_gist(bot, '\n\n'.join(msgs))
+            url = create_list(bot, '\n\n'.join(msgs))
             if not url:
                 return
-            bot.memory['command-gist'] = (len(bot.command_groups), url)
+            bot.memory['command-list'] = (len(bot.command_groups), url)
         bot.say("I've posted a list of my commands at {} - You can see "
                 "more info about any of these commands by doing .help "
                 "<command> (e.g. .help time)".format(url))
 
 
-def create_gist(bot, msg):
-    payload = {
-        'description': 'Command listing for {}@{}'.format(bot.nick, bot.config.core.host),
-        'public': 'true',
-        'files': {
-            'commands.txt': {
-                "content": msg,
-            },
-        },
-    }
+def create_list(bot, msg):
+    msg = 'Command listing for {}@{}\n\n'.format(bot.nick, bot.config.core.host) + msg
+    payload = { "content": msg }
+    headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
+    
     try:
-        result = requests.post('https://api.github.com/gists',
-                               data=json.dumps(payload))
+        result = requests.post('https://ptpb.pw/', json=payload, headers=headers)
     except requests.RequestException:
         bot.say("Sorry! Something went wrong.")
-        logger.exception("Error posting commands gist")
-        return
-    if not result.status_code != '201':
-        bot.say("Sorry! Something went wrong.")
-        logger.error("Error %s posting commands gist: %s",
-                     result.status_code, result.text)
+        logger.exception("Error posting commands")
         return
     result = result.json()
-    if 'html_url' not in result:
+    if 'url' not in result:
         bot.say("Sorry! Something went wrong.")
         logger.error("Invalid result %s", result)
         return
-    return result['html_url']
+    return result['url']
 
 
 @rule('$nick' r'(?i)help(?:[?!]+)?$')


Test patch: