Created
January 3, 2016 14:58
-
-
Save lordscales91/a501b794f38455c5320c to your computer and use it in GitHub Desktop.
This is a Python3 compatible version of SolveMedia's official Python library. https://portal.solvemedia.com/portal/help/pub/python/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright (c) 2009 by Jeff Weisberg | |
# Author: Jeff Weisberg | |
# Created: 2009-Jun-25 13:18 (EDT) | |
# Function: python solvemedia interface | |
# | |
# $Id$ | |
# Python3 compatibility implemented by lordscales91 | |
# with the help of the six compatibility layer | |
import six | |
from six.moves import urllib # @UnresolvedImport Ignore flag for Eclipse PyDev | |
import hashlib | |
# solvemedia servers: | |
ADCOPY_API_HTTP = "http://api.solvemedia.com" | |
ADCOPY_API_HTTPS = "https://api-secure.solvemedia.com" | |
ADCOPY_VERIFY_HTTP = "http://verify.solvemedia.com/papi/verify" | |
ADCOPY_SIGNUP_HTTP = "http://api.solvemedia.com/public/signup" | |
# create solvemedia object: | |
# c = libsolvemedia.Solvemedia( ckey, vkey, hkey ) | |
# ckey - your solvemedia api ckey | |
# vkey - your solvemedia api vkey | |
# hkey - your solvemedia api hkey | |
# | |
# c.get_html( errorp, usessl ) | |
# get html for the solvemedia widget | |
# errorp - display an error message on the widget | |
# usessl - use ssl | |
# | |
# c.check_answer( remoteip, challenge, response ) | |
# check the user's answer | |
# remoteip - the user's IP address | |
# challenge - the solvemedia puzzle challenge id | |
# response - the user's answer | |
# util methods for Python3 compatibility: | |
def safe_concat(*items): | |
""" | |
Safe method for concatenating strings with bytestrings | |
""" | |
result = '' | |
for item in items: | |
if not isinstance(item, six.string_types): | |
item = item.decode() | |
result += item | |
return result | |
def force_string(value): | |
if not isinstance(value, six.string_types): | |
value = value.decode() | |
return value | |
def force_bytes(value): | |
if isinstance(value, six.string_types): | |
return value.encode() | |
return value | |
class SolveMedia: | |
def __init__(self, ckey, vkey, hkey): | |
self.ckey = ckey | |
self.vkey = vkey | |
self.hkey = hkey | |
def get_html(self, errorp=False, usessl=False): | |
if usessl: | |
server = ADCOPY_API_HTTPS | |
else: | |
server = ADCOPY_API_HTTP | |
if errorp: | |
param = ";error=1" | |
else: | |
param = "" | |
html = """ | |
<!-- start solvemedia puzzle widget --> | |
<script type="text/javascript" | |
src="%(baseurl)s/papi/challenge.script?k=%(ckey)s%(param)s"> | |
</script> | |
<noscript> | |
<iframe src="%(baseurl)s/papi/challenge.noscript?k=%(ckey)s%(param)s" | |
height="300" width="500" frameborder="0"></iframe><br> | |
<textarea name="adcopy_challenge" rows="3" cols="40"> | |
</textarea> | |
<input type="hidden" name="adcopy_response" | |
value="manual_challenge"> | |
</noscript> | |
<!-- end solvemedia puzzle widget --> | |
""" % { | |
'ckey': self.ckey, | |
'baseurl': server, | |
'param': param, | |
} | |
return html | |
def check_answer(self, remoteip, challenge, response): | |
data = urllib.parse.urlencode({'privatekey': self.vkey, | |
'remoteip': remoteip, | |
'challenge': challenge, | |
'response': response}) | |
req = urllib.request.Request( | |
ADCOPY_VERIFY_HTTP, | |
force_bytes(data), { | |
'User-Agent': 'solvemedia-python-client', | |
}) | |
try: | |
resp = urllib.request.urlopen(req) | |
except: | |
return {'is_valid': False, 'error': 'server error'} | |
line = resp.read().splitlines() | |
# validate message authenticator | |
if self.hkey: | |
base = safe_concat(line[0], challenge, self.hkey) | |
hash_check = hashlib.sha1(force_bytes(base)).hexdigest() | |
if hash_check != force_string(line[2]): | |
return {'is_valid': False, 'error': 'hash-fail'} | |
if force_string(line[0]) == 'true': | |
return {'is_valid': True} | |
else: | |
return {'is_valid': False, 'error': line[1]} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment