Creating badge via API query works, but returns 422


(Jay Pfaffman) #1

I want a way to make groups of badges:

  • bronze -> submitted with certain tag
  • silver -> submitted tag, liked by me
  • gold -> submitted tag, liked by me and 3 other people

I need to make a bunch of them and it’s tedious doing it from the web interface. One day I’ll write a plugin, but until then, I thought I’d do a quick Python script.

I had given up, as it fails with

urllib.error.HTTPError: HTTP Error 422: Unprocessable Entity

but when I glanced again at the badges admin page, I found that my badge had indeed been created. I guess maybe I don’t care, as it does work, but any ideas on why I get this error?

I added a bunch of headers thinking that might somehow help. It didn’t seem to (but they don’t seem to have hurt, either).

Code

#!/usr/bin/python3
from urllib.request import Request, urlopen
from urllib.error import URLError
import urllib.parse
API_USERNAME = 'pfaffman'
API_KEY = 'KEY'
BADGE = 'API BADGE2.2'

url = 'https://literatecomputing.com/admin/badges'

values = {'allow_title' : 'true',
          'multiple_grant' : 'true',
          'listable' : 'true',
          'auto_revoke' : 'false',
          'enabled' : 'false',
          'show_posts' : 'true',
          'target_posts' : 'true',
          'icon' : 'fa-certificate',
          'image' : '',
          'name' : BADGE,
          'description' : 'testing 1, 2, 3',
          'query' : """SELECT p.user_id, min(p.created_at) granted_at, MIN(p.id) post_id
FROM badge_posts p
JOIN topics t ON t.id = p.topic_id
JOIN topic_custom_fields tcf on t.id = tcf.topic_id
JOIN post_actions pa ON pa.post_id = p.id AND 
      post_action_type_id = (
                SELECT id FROM post_action_types WHERE name_key = 'like'
       ) AND 
       pa.user_id IN (
           SELECT gu.user_id
           FROM group_users gu
           WHERE gu.group_id = ( SELECT id FROM groups WHERE name ilike 'Leader' ) 
       )
WHERE category_id = ANY (
  SELECT id FROM categories WHERE name ilike '%completions%'
) AND p.post_number = 1
AND p.like_count > 0
AND tcf.name LIKE 'tags' and tcf.value LIKE '%wordpress-basics%'
and (:backfill OR ( p.id IN (:post_ids) ))
GROUP BY p.user_id
""",
'badge_grouping_id' : '7',
'trigger' : '2',
'badge_type_id' : '1',
'api_username' : API_USERNAME,
'api_key' : API_KEY
}

headers = {'content-type' : 'application/x-www-form-urlencoded; charset=UTF-8',
           'x-requested-with' : 'XMLHttpRequest',
           'referer' :'https://literatecomputing.com/admin/badges/new',
           'origin' : 'https://literatecomputing.com',
           'user-agent' : 'discourseBadgeCreator',
           'referer' : 'https://literatecomputing.com/admin/badges/new',
           'content-type' : 'application/x-www-form-urlencoded; charset=UTF-8'}


data = urllib.parse.urlencode(values)
data = data.encode('ascii') 
req = urllib.request.Request(url, data, headers)

print("\n\nvalues: ", data)

try: urllib.request.urlopen(req)
except URLError as e:    
    print ("\n\n--------------------YO!--------------------\n\n" , e.reason)
    print ("\n\nHeaders:\n\n ", e.headers)

with urllib.request.urlopen(req) as response:
    if response.code == '200':
        print ("It worked!")
    else:
        print ("Darn.")


Show badges on topics that earn them