I am making a python twitch.tv API Wrapper for python and so far I have :
import urllib2
import json
import time
waittime = 1
baseurl = 'https://api.twitch.tv/kraken/'
secret = '(CLASSIFIED)'
class twitchchannelinfo(): #Ignore me ;D I'm Here for reference's sake
def __init__ (self,channel):
self.channel = channel
time.sleep(waittime)
self.dict1 = json.loads(urllib2.urlopen(baseurl + 'channels/' + channel).read())
def getstatus(self):
return self.dict1 ['status']
def getdisplay_name(self):
return self.dict1 ['display_name']
def getmature(self):
return self.dict1 ['mature']
def getchanurl(self):
return self.dict1 ['url']
def getcreated_at(self):
return self.dict1 ['created_at']
def getteams(self):
return self.dict1 ['teams']
def getgame(self):
return self.dict1 ['game']
def getupdated_at(self):
return self.dict1 ['updated_at']
class twichtvwrapper():
def __init__(self,username,password):
self.username = username
self.password = password
self.dict1 = json.loads(urllib2.urlopen(baseurl + 'oauth2/token',\
"client_id=<3kfp6al05voejvv7ofmpc94g4jga0tb>&\
client_secret=<" + secret + ">&\
username=<" + self.username + ">&\
password=<" + self.password + ">&\
scope=user_read&\
grant_type=password"))
print self.dict1
me = twichtvwrapper('martincharles07','(CLASSIFIED)')
(The secret is an API identifier and the password has been retracted for obvious reasons ;D).
The server should return a JSON response like this:
{
"scope":["user_read"],
"access_token":"df4yofxyn2s7240ojfrh9chz8"
}
Here is the API reference.
The program crashes with the exception urllib2.HTTPError: HTTP Error 400: Bad Request. I don't know what I am doing wrong, is it the line splits or incorrect usage of urllib2? How can I fix it?
Instead of concatenating your string together try something like
body={'username':'someusername','password':'somepassword', ...}
txdata = urllib.urlencode(body)
You'll have to use urllib instead of urllib2 to use that method.
Here's an untested snippet.
import json
import urllib
import urllib2
def wrapper(user, password, secret):
data = {"client_id":"<3kfp6al05voejvv7ofmpc94g4jga0tb>",
"client_secret":secret,
"username":username,
"password":password,
"scope":"user_read",
"grant_type":"password",
}
txdata = urllib.urlencode(data)
response = urllib2.urlopen(baseurl + 'oauth2/token', txdata)
return_data = json.loads(response.read())
return return_data
Related
I have this Python script to control a PfSense router via FauxAPI. The problem is that when i call a function it gives an error. I think i'm calling the function wrong. Does anyone know how to call them?
Here is a link to the API i'm using: https://github.com/ndejong/pfsense_fauxapi
I have tried calling config_get(self, section=none) but that does not seem to work.
import os
import json
import base64
import urllib
import requests
import datetime
import hashlib
class PfsenseFauxapiException(Exception):
pass
class PfsenseFauxapi:
host = '172.16.1.1'
proto = None
debug = None
version = None
apikey = 'key'
apisecret = 'secret'
use_verified_https = None
def __init__(self, host, apikey, apisecret, use_verified_https=False, debug=False):
self.proto = 'https'
self.base_url = 'fauxapi/v1'
self.version = __version__
self.host = host
self.apikey = apikey
self.apisecret = apisecret
self.use_verified_https = use_verified_https
self.debug = debug
if self.use_verified_https is False:
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
def config_get(self, section=None):
config = self._api_request('GET', 'config_get')
if section is None:
return config['data']['config']
elif section in config['data']['config']:
return config['data']['config'][section]
raise PfsenseFauxapiException('Unable to complete config_get request, section is unknown', section)
def config_set(self, config, section=None):
if section is None:
config_new = config
else:
config_new = self.config_get(section=None)
config_new[section] = config
return self._api_request('POST', 'config_set', data=config_new)
def config_patch(self, config):
return self._api_request('POST', 'config_patch', data=config)
def config_reload(self):
return self._api_request('GET', 'config_reload')
def config_backup(self):
return self._api_request('GET', 'config_backup')
def config_backup_list(self):
return self._api_request('GET', 'config_backup_list')
def config_restore(self, config_file):
return self._api_request('GET', 'config_restore', params={'config_file': config_file})
def send_event(self, command):
return self._api_request('POST', 'send_event', data=[command])
def system_reboot(self):
return self._api_request('GET', 'system_reboot')
def system_stats(self):
return self._api_request('GET', 'system_stats')
def interface_stats(self, interface):
return self._api_request('GET', 'interface_stats', params={'interface': interface})
def gateway_status(self):
return self._api_request('GET', 'gateway_status')
def rule_get(self, rule_number=None):
return self._api_request('GET', 'rule_get', params={'rule_number': rule_number})
def alias_update_urltables(self, table=None):
if table is not None:
return self._api_request('GET', 'alias_update_urltables', params={'table': table})
return self._api_request('GET', 'alias_update_urltables')
def function_call(self, data):
return self._api_request('POST', 'function_call', data=data)
def system_info(self):
return self._api_request('GET', 'system_info')
def _api_request(self, method, action, params=None, data=None):
if params is None:
params = {}
if self.debug:
params['__debug'] = 'true'
url = '{proto}://{host}/{base_url}/?action={action}&{params}'.format(
proto=self.proto, host=self.host, base_url=self.base_url, action=action, params=urllib.parse.urlencode(params))
if method.upper() == 'GET':
res = requests.get(
url,
headers={'fauxapi-auth': self._generate_auth()},
verify=self.use_verified_https
)
elif method.upper() == 'POST':
res = requests.post(
url,
headers={'fauxapi-auth': self._generate_auth()},
verify=self.use_verified_https,
data=json.dumps(data)
)
else:
raise PfsenseFauxapiException('Request method not supported!', method)
if res.status_code == 404:
raise PfsenseFauxapiException('Unable to find FauxAPI on target host, is it installed?')
elif res.status_code != 200:
raise PfsenseFauxapiException('Unable to complete {}() request'.format(action), json.loads(res.text))
return self._json_parse(res.text)
def _generate_auth(self):
# auth = apikey:timestamp:nonce:HASH(apisecret:timestamp:nonce)
nonce = base64.b64encode(os.urandom(40)).decode('utf-8').replace('=', '').replace('/', '').replace('+', '')[0:8]
timestamp = datetime.datetime.utcnow().strftime('%Y%m%dZ%H%M%S')
hash = hashlib.sha256('{}{}{}'.format(self.apisecret, timestamp, nonce).encode('utf-8')).hexdigest()
return '{}:{}:{}:{}'.format(self.apikey, timestamp, nonce, hash)
def _json_parse(self, data):
try:
return json.loads(data)
except json.JSONDecodeError:
pass
raise PfsenseFauxapiException('Unable to parse response data!', data)
Without having tested the above script myself, I can conclude that yes you are calling the function wrong. The above script is rather a class that must be instantiated before any function inside can be used.
For example you could first create an object with:
pfsense = PfsenseFauxapi(host='<host>', apikey='<API key>', apisecret='<API secret>')
replacing <host>, <API key> and <API secret> with the required values
Then call the function with:
pfsense.config_get() # self is not passed
where config_get can be replaced with any function
Also note
As soon as you call pfsense = PfsenseFauxapi(...), all the code in
the __init__ function is also run as it is the constructor (which
is used to initialize all the attributes of the class).
When a function has a parameter which is parameter=something, that something is the default value when nothing is passed for that parameter. Hence why use_verified_https, debug and section do not need to be passed (unless you want to change them of course)
Here is some more information on classes if you need.
You need to create an object of the class in order to call the functions of the class. For example
x = PfsenseFauxapi() (the init method is called during contructing the object)
and then go by x.'any function'. Maybe name the variable not x for a good naming quality.
I'm having some issues creating a basic python module using inherited classes. I keen getting RecursionError: maximum recursion depth exceeded. Below is a snippet of how I'm wanting my code to work:
from foo import Client
x = Client()
y = x.contacts.me()
How do I structure my classes to accommodate the syntax above?
Here's what I have in my __init__.py:
class Client:
def __init__(self, access_token=None):
self.access_token = access_token
self.base_endpoint = 'https://someapi.com'
self.contacts = self._contacts()
def _contacts(self):
from foo.contacts import Contacts
self.contacts = Contacts(self)
return self.contacts
And in my contacts.py:
from foo import Client
import requests
class Contacts(Client):
def me(self):
response = requests.get(self.base_endpoint + 'contacts/me', headers={'Authorization': 'Bearer ' + self.access_token})
return response.json()
I've created a script in python using class to log into a website making use of my credentials. When I run my script, I can see that it successfully logs in. What I can't do is find a suitable way to pass res.text being returned within login() method to get_data() method so that I can process it further. I don't wish to try like this return self.get_data(res.text) as it looks very awkward.
The bottom line is: when I run my script, It will automatically logs in like it is doing now. However, it will fetch data when I use this line scraper.get_data() within main function..
This is my try so far:
from lxml.html import fromstring
import requests
class CoffeeGuideBot(object):
login_url = "some url"
def __init__(self,session,username,password):
self.session = session
self.usrname = username
self.password = password
self.login(session,username,password)
def login(self,session,username,password):
session.headers['User-Agent'] = 'Mozilla/5.0'
payload = {
"Login1$UserName": username,
"Login1$Password": password,
"Login1$LoginButton": "Log on"
}
res = session.post(self.login_url,data=payload)
return res.text
def get_data(self,htmlcontent):
root = fromstring(htmlcontent,"lxml")
for iteminfo in root.cssselect("some selector"):
print(iteminfo.text)
if __name__ == '__main__':
session = requests.Session()
scraper = CoffeeGuideBot(session,"username","password")
#scraper.get_data() #This is how i wish to call this
What is the ideal way to pass variable as parameter between methods?
If I understood you requirement correctly, you want to access res.text inside get_data() without passing it as a method argument.
There are 2 options IMO.
Store res as a class instance variable of CoffeeGuideBot, access it in get_data()
def login(self,session,username,password):
<some code>
self.res = session.post(self.login_url,data=payload)
def get_data(self):
root = fromstring(self.res.text,"lxml")
<other code>
Almost same as above, but actually use the return value from login() to store res. In current code, the return statement is unnecessary.
def __init__(self,session,username,password):
<initializations>
self.res = self.login(session,username,password)
def login(self,session,username,password):
<some code>
return session.post(self.login_url,data=payload)
def get_data(self):
root = fromstring(self.res.text,"lxml")
<other code>
from lxml.html import fromstring
import requests
class CoffeeGuideBot(object):
login_url = "some url"
def __init__(self,session,username,password):
self.session = session
self.usrname = username
self.password = password
self._login = self.login(session,username,password)
def login(self,session,username,password):
session.headers['User-Agent'] = 'Mozilla/5.0'
payload = {
"Login1$UserName": username,
"Login1$Password": password,
"Login1$LoginButton": "Log on"
}
res = session.post(self.login_url,data=payload)
return res.text
def get_data(self):
htmlcontent = self._login
root = fromstring(htmlcontent,"lxml")
for iteminfo in root.cssselect("some selector"):
print(iteminfo.text)
if __name__ == '__main__':
session = requests.Session()
scraper = CoffeeGuideBot(session,"username","password")
scraper.get_data()
I am calling Blockchain.INFO's API using a Python libary from GitHub: https://github.com/gowness/pyblockchain
My code can be seen below, when I run the code I get no returned value. I dont have the best knowledge on classes etc but I have read briefly, what is going wrong here?
import requests
import urllib
import json
from os.path import expanduser
import configparser
class Wallet:
guid = 'g'
isAccount = 0
isKey = 0
password1 = 'x'
password2 = 'y'
url = ''
def __init__(self, guid = 'g', password1 = 'x', password2 = 'y'):
if guid.count('-') > 0:
self.isAccount = 1
if password1 == '': # wallet guid's contain -
raise ValueError('No password with guid.')
else:
self.isKey = 1
self.guid = guid
self.url = 'https://blockchain.info/merchant/' + guid + '/'
self.password1 = password1
self.password2 = password2
def Call(self, method, data = {}):
if self.password1 != '':
data['password'] = self.password1
if self.password2 != '':
data['second_password'] = self.password2
response = requests.post(self.url + method,params=data)
json = response.json()
if 'error' in json:
raise RuntimeError('ERROR: ' + json['error'])
return json
def GetBalance(self):
response = self.Call('balance')
return response['balance']
Wallet().GetBalance()
Since I cannot run a successful POST call against your URL, I slightly changed your code so that it does not look for 'error' in json, as to see what happens inside your GetBalance method.
Now, knowing that by making a call that will fail, the json response will be this:
{u'error': u'Unknown Key Format'}
So, inside your GetBalance method, I simply added a print statement after
response = self.Call('balance')
And I got a valid json as expected.
All this to say. Try doing this and see what you get:
print(Wallet().GetBalance())
Based on the response that is coming back, maybe this is indicating that you are not providing the appropriate payload to the server for that POST method you are trying to make?
I'm having trouble running the code below.
The code should work (it's a Udacity source code solution for a problem set). It should run on Google App Engine.
In my terminal, I navigate to the hw2 folder which contains the following files at ~/python-docs-samples/appengine/standard
Then I run
dev_appserver.py .
However, I get a 404 error when I load the page at localhost:8080
It works fine for a 'Hello World' example in ~/python-docs-samples/appengine/standard
What am I doing wrong here? Thanks
import os
import re
from string import letters
import webapp2
import jinja2
from google.appengine.ext import db
template_dir = os.path.join(os.path.dirname(__file__), 'templates')
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir),
autoescape = True)
def render_str(template, **params):
t = jinja_env.get_template(template)
return t.render(params)
class BaseHandler(webapp2.RequestHandler):
def render(self, template, **kw):
self.response.out.write(render_str(template, **kw))
def write(self, *a, **kw):
self.response.out.write(*a, **kw)
class Rot13(BaseHandler):
def get(self):
self.render('rot13-form.html')
def post(self):
rot13 = ''
text = self.request.get('text')
if text:
rot13 = text.encode('rot13')
self.render('rot13-form.html', text = rot13)
USER_RE = re.compile(r"^[a-zA-Z0-9_-]{3,20}$")
def valid_username(username):
return username and USER_RE.match(username)
PASS_RE = re.compile(r"^.{3,20}$")
def valid_password(password):
return password and PASS_RE.match(password)
EMAIL_RE = re.compile(r'^[\S]+#[\S]+\.[\S]+$')
def valid_email(email):
return not email or EMAIL_RE.match(email)
class Signup(BaseHandler):
def get(self):
self.render("signup-form.html")
def post(self):
have_error = False
username = self.request.get('username')
password = self.request.get('password')
verify = self.request.get('verify')
email = self.request.get('email')
params = dict(username = username,
email = email)
if not valid_username(username):
params['error_username'] = "That's not a valid username."
have_error = True
if not valid_password(password):
params['error_password'] = "That wasn't a valid password."
have_error = True
elif password != verify:
params['error_verify'] = "Your passwords didn't match."
have_error = True
if not valid_email(email):
params['error_email'] = "That's not a valid email."
have_error = True
if have_error:
self.render('signup-form.html', **params)
else:
self.redirect('/unit2/welcome?username=' + username)
class Welcome(BaseHandler):
def get(self):
username = self.request.get('username')
if valid_username(username):
self.render('welcome.html', username = username)
else:
self.redirect('/unit2/signup')
app = webapp2.WSGIApplication([('/unit2/rot13', Rot13),
('/unit2/signup', Signup),
('/unit2/welcome', Welcome)],
debug=True)
The following code defines the request handlers for the corresponding URL patterns:
app = webapp2.WSGIApplication([('/unit2/rot13', Rot13),
('/unit2/signup', Signup),
('/unit2/welcome', Welcome)],
debug=True)
Notice that you do not have a handler for / or a catch all. This is why you're getting an HTTP 404 error.