Python passing variable - python

I am trying to figure out why I cannot pass my two variables to get the API call to work. I know the API call works when I put static name/key in their places.
Any help would be appreciated.
import httplib
#Print my list to choose from.
servers = {'server1.com':'#######','server2.com':'######'}
for server, key in servers.items():
print server
#User chooses which node, it should print what they chose, then store into
variable to send for API Post.
node = raw_input("Which node would you like to check Network Bytes for? ")
if node == server:
print serves.item(server)
print servers.item(key)
box = servers.item(server)
api = servers.item(key)
headers = {'Content-Type': 'application/json', 'Accept': 'application/json',
'Authorization': 'GetData apikey=' + api}
body = r"""{
"cycle": "5min",
"from": 0,
"metric_category": "net",
"metric_specs": [
{
"name": "bytes_in"
}
],
"object_ids": [
0
],
"object_type": "device",
"until": 0
}
"""
conn = httplib.HTTPSConnection(box)
conn.request('POST', '/api/v1/metrics', headers=headers, body=body)
resp = conn.getresponse()
print resp.read()

You should use the json module to translate the Python dict (headers) into a json object. Although they are similar the syntax is subtly different.
The other issue I see here is that server is undefined when you are testing for it. You created server in the for loop, but it's fallen out of scope before you if node == server:. Perhaps you could replace that part with:
#User chooses which node, it should print what they chose, then store into
variable to send for API Post.
box = raw_input("Which node would you like to check Network Bytes for? ")
api = servers.get(node, None):
print "box/node:", box
print " api :", api

Your loop logic is incorrect, as it iterates the dictionary but always will hold the last k,v pair.
servers = {'server1.com':'#######','server2.com':'######'}
for server, key in servers.items():
print server
That basically means every time this runs, it will end holding the same value from the dict. You shouldn't use server / key variables outside of your loop, it's not right and you can expect strange behavior
But the issue resides in your dict retrieval
if node == server:
**print serves.item(server)** # there's a typo here
print servers.item(key)
box = servers.item(server)
api = servers.item(key)
If you want to get the value of a key from a dict, use servers.get(server) or servers[server].
And I'm not sure why are you checking if node == server? you can eliminate that and just ask for node directly from servers dict: box = servers.get(node)

Related

Automatically subscribe to YouTube channels via Channel_ID

I'm fairly new to Python and I'm trying to migrate subscriptions from an older youtube account to a newer one that I'll use going forward. I pulled my subscriptions export from the old one and have around 470+ subs that I'll need to migrate over.
I found this article which absolutely works with automatically subscribing to a youtube channel via their channel_id but it seems like in the key value pair I can only run the .py script once per value.
I tried all sorts of googling to see how I can include multiple values in the key (channelId) but it always only auto subs to the last one in the dictionary.
Can someone please help show me what I'm missing? I feel like there has to be a way to add multiple channelId values in there key dictionary, right?!
Here's what my code looks like > screenshot
import os
import google.oauth2.credentials
import google_auth_oauthlib.flow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google_auth_oauthlib.flow import InstalledAppFlow
# The CLIENT_SECRETS_FILE variable specifies
# the name of a file that contains
# client_id and client_secret.
CLIENT_SECRETS_FILE = "client_secret.json"
# This scope allows for full read/write access
# to the authenticated user's account and
# requires requests to use an SSL connection.
SCOPES = ['https://www.googleapis.com/auth/youtube.force-ssl']
API_SERVICE_NAME = 'youtube'
API_VERSION = 'v3'
def get_authenticated_service():
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES)
credentials = flow.run_console()
return build(API_SERVICE_NAME, API_VERSION, credentials = credentials)
def print_response(response):
print(response)
# Build a resource based on a list of
# properties given as key-value pairs.
# Leave properties with empty values out
# of the inserted resource.
def build_resource(properties):
resource = {}
for p in properties:
# Given a key like "snippet.title", split into
# "snippet" and "title", where "snippet" will be
# an object and "title" will be a property in that object.
prop_array = p.split('.')
ref = resource
for pa in range(0, len(prop_array)):
is_array = False
key = prop_array[pa]
# For properties that have array values, convert a name like
# "snippet.tags[]" to snippet.tags, and set a flag to handle
# the value as an array.
if key[-2:] == '[]':
key = key[0:len(key)-2:]
is_array = True
if pa == (len(prop_array) - 1):
# Leave properties without values
# out of inserted resource.
if properties[p]:
if is_array:
ref[key] = properties[p].split(', ')
else:
ref[key] = properties[p]
elif key not in ref:
# For example, the property is "snippet.title",
# but the resource does not yet have a "snippet"
# object. Create the snippet object here.
# Setting "ref = ref[key]" means that in the
# next time through the "for pa in range ..." loop,
# we will be setting a property in the
# resource's "snippet" object.
ref[key] = {}
ref = ref[key]
else:
# For example, the property is "snippet.description",
# and the resource already has a "snippet" object.
ref = ref[key]
return resource
# Remove keyword arguments that are not set
def remove_empty_kwargs(**kwargs):
good_kwargs = {}
if kwargs is not None:
for key, value in kwargs.items():
if value:
good_kwargs[key] = value
return good_kwargs
def subscriptions_insert(client, properties, **kwargs):
resource = build_resource(properties)
kwargs = remove_empty_kwargs(**kwargs)
response = client.subscriptions().insert(
body = resource,**kwargs).execute()
return print_response(response)
if __name__ == '__main__':
# When running locally, disable OAuthlib's
# HTTPs verification. When running in production
# * do not * leave this option enabled.
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
client = get_authenticated_service()
subscriptions_insert(client,
{'snippet.resourceId.kind': 'youtube# channel',
'snippet.resourceId.channelId': 'UC09fL42MpkktKZWmWxYiDhw', 'UC0Q7Hlz75NYhYAuq6O0fqHw'},
part ='snippet')```
According to YouTube Data API v3 documentation (Subscriptions: insert endpoint and Subscriptions resource), it seems that you can only subscribe a channel at a time. As you have by default 10,000 of quota per day, except if you request extended quota, because Subscriptions: insert costs 50 of quota, then for 470+ subscriptions, you would need 3 days to proceed.
Otherwise you can proceed as follows, it seems that the first time I tried with ~500 channels I have been subscribed to ~290 of them but now I mostly only receive (when removing -H 'Accept-Encoding: gzip, deflate, br' from the cURL request):
{
"error": {
"code": 429,
"message": "Resource has been exhausted (e.g. check quota).",
"errors": [
{
"message": "Resource has been exhausted (e.g. check quota).",
"domain": "global",
"reason": "rateLimitExceeded"
}
],
"status": "RESOURCE_EXHAUSTED"
}
}
So it's an unsure method that you can try to deepen.
Ever wondered how to do that in a single request without using any quota?
Go on an ad hoc YouTube channel YOUR_CHANNEL that you want to subscribed to: https://www.youtube.com/channel/YOUR_CHANNEL_ID
Open the Network tab of your web-browser by using Ctrl + Shift + E (on Firefox) and filter XHR requests.
Now click on Subscribe.
You should see a request to subscribe, copy it as cURL (by right-clicking).
Change at the end
"channelIds":["YOUR_CHANNEL_ID"]
to:
"channelIds":["YOUR_CHANNEL_ID_0, YOUR_CHANNEL_ID_1, ..., YOUR_CHANNEL_ID_499"]
Where YOUR_CHANNEL_ID_0 is your YOUR_CHANNEL_ID and YOUR_CHANNEL_ID_1 the second channel you want to subscribe to and so forth.
Execute the modified cURL request in a terminal and that's it!
Note that this webpage contains a subscriptions count and this one contains all your subscriptions.
To get more than 249 different channels, I used:
import requests, json
channelIds = set()
pageToken = ''
API_KEY = 'AIzaSy...'
i = 0
while len(channelIds) < 250:
url = f'https://www.googleapis.com/youtube/v3/search?q={i}&type=channel&maxResults=50&key={API_KEY}'
if pageToken != '':
url += f"&pageToken={pageToken}"
content = requests.get(url).text
data = json.loads(content)
for item in data['items']:
channelIds.add(item['id']['channelId'])
print(len(channelIds))
if 'nextPageToken' in data:
pageToken = data['nextPageToken']
else:
break
i += 1
print('["' + '","'.join(channelIds) + '"]', len(channelIds))
As #Benjamin Loison has mentioned, there is a quota on the limit on the usage of the API. If you'd like to raise the limit, I think there is a form you can fill out to request more. However, I don't recommend you do so since the form is applicable mainly for a large application that will be used for a long time and involve a long process of human inspection on what you're trying to build (This is based on my personal experience, might not be entirely accurate).
My suggestion would be to use the script you have to print out a list of channel links, and you can click into each of them and press the subscribe button. 470-ish channels should not take you a long time.

PagerDuty assignments list empty

How can I get "assignments" key of the incidents in PagerDuty? I have a python script which returns info on particular incident, but the list with assignments is empty.
#!/usr/bin/env python
import requests
import json
API_KEY = 'iiiiiiiiiiiiiiiiii'
# incident ID
ID = 'PPPPP'
def get_incident():
url = 'https://api.pagerduty.com/incidents/{id}'.format(id=ID)
headers = {
'Accept': 'application/vnd.pagerduty+json;version=2',
'Authorization': 'Token token={token}'.format(token=API_KEY)
}
params = {
'include': 'assignees',
'time_zone': 'Europe/Sofia'
}
r = requests.get(url, headers=headers,data=json.dumps(params))
print ('Status Code: {code}'.format(code=r.status_code))
print (r.json())
if __name__ == '__main__':
get_incident()
In their documentation here there are entries for that key, see on the picture bellow:
How can I achieve that?
Based on experimentation, it appears that assignments are only populated while an incident is still active. I just queried /incidents/id for an incident in the triggered state and in the resolved state, the triggered one shows an assignment while the resolved one does not.
It's kind of frustrating, because I want to look at the LogEntrys for an incident via their API and I haven't figured that out yet.
The alert_counts field always seems to contain zeros too, which doesn't make any sense.

unable to retrieve tornado secure cookie

for some reason I'm unable to retrieve a secure cookie I've set with tornado. Using firebug I can see the cookie and it's expiration date, but when I try to print or retrieve it, it keeps coming up as None. Is there some way I'm invalidating it that I can't see. This is the code I'm using:
class loginHandler(tornado.web.RequestHandler):
def post(self):
# first type of request made to this page is a post
userEmail = self.get_argument("username")
password = self.get_argument("password")
deviceType = self.get_argument("deviceType")
# get some info from the client header
userIp = self.request.headers['X-Real-Ip']
userAgentInfo = self.request.headers['User-Agent']
result = pumpkinsdb.loginUser(userEmail, password, deviceType, userIp, userAgentInfo)
if result == None:
self.redirect("/")
else:
fullname = pumpkinsdb.pumpkinsdb_user['fullName']
this_page_title = fullname if fullname else pumpkinsdb.pumpkinsdb_user['userEmail']
# successful login set up user's cookies
# self.set_secure_cookie("memberId", str(user['memberId']), expires_days=0.1, secure=True, httponly=True)
self.set_secure_cookie("memberId", str(pumpkinsdb.pumpkinsdb_user['memberId']))
self.write(str(self.get_secure_cookie("memberId")))
time_now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print "{} [{}::get] pid[{}] login requested for user: [{}] from [{}] using [{}]".format(
time_now, self.__class__.__name__, os.getpid(), pumpkinsdb.pumpkinsdb_user['emailAddress'],
pumpkinsdb.pumpkinsdb_user['userIp'], pumpkinsdb.pumpkinsdb_user['userAgentInfo'])
self.render('calendar.html', title = this_page_title)
def get(self):
validSession = self.get_secure_cookie("memberId")
if validSession:
this_page_title = pumpkinsdb.pumpkinsdb_user['fullName']
self.render('calendar.html', title = this_page_title)
else:
print self.get_secure_cookie("memberId")
self.write(str(validSession))
Is your cookie secret changing somehow when you restart the server? If the cookie secret changes, all existing cookies are invalidated. Note that even though the cookie secret should be randomly generated, this doesn't mean you should have something like cookie_secret=os.urandom(16) in your code, because that will generate a new secret every time. Instead, you need to call os.urandom once and save its output somewhere (keep it safe and private, like your TLS keys).
so basically the problem was I had four tornado processes running behind nginx and for each tornado process I generated a unique random string with:
cookie_secret = base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes)
obviously that was my problem because each tornado process had a different secret so when i tried to read it tornado thought it was invalid.
The key is to generate a unique random string but then store it somewhere secure such as in your options:
define(cookie_secret, "934893012jer9834jkkx;#$592920231####")
or whatever string you deem fit.
Thank you to everyone that responded. sorry about that.

SPOJ command line submission: What to include in POST method?

Right now I am writing a snippet allowing submitting code to http://www.spoj.com/ from command line, i.e. something like python spoj_cl.py test.cpp
I understand that I need to send a POST request to the corresponding URL with specified parameters and cookie, but I'm still confused on which parameters to include on. Right now I'm doing it in a trial-and-error method, which seems not to be very effective. My questions are:
How to check systematically which parameters to be included in when sending a POST request?
How can I check immediately if the POST request I send is successful? One way I could think of is to get the content of the submission page http://www.spoj.com/status/, but checking the request directly should be preferable.
Below is the snippet I'm working on. Hopefully it should be readable.
import requests, sys
# if __name__ == "__main__":
base_url = "http://spoj.com"
autologin_hash = "*************" # Your user hash, taken from cookie
autologin_login = "************" # Your user name
session_id = "************" # Login session, can be retrieved when logged in
cookies_info = {
"autologin_login": autologin_login,
"autologin_hash": autologin_hash
}
ext_id = {
"cpp": "1"
}
filename = "test.cpp"
problem_name = str(filename.split(".")[0]).upper()
extension = filename.split(".")[1]
submit_url = base_url + "/submit/"
parts = {
"PHPSESSID": session_id,
"action": "/submit/complete",
"file": open(filename, "rb"),
"subm_file": "",
"lang": ext_id[extension],
"problemcode": problem_name
}
requests.post(submit_url,
params={"PHPSESSID": session_id},
files=parts,
cookies=cookies_info)
print "Submission sent!"
How to check systematically which parameters to be included in when sending a POST request?
I am not a member of the site spoj.com, but what you are asking for is basic web scraping. Find the HTML form for submitting code on the website, then use Firebug or Chrome developer console to find the HTML input elements with name attributes. Once you have found them, you can make a Python script to check for these elements systematically. If one day the elements are missing, the page probably changed.
Example Code:
webpage = requests.get(form_url, params={"PHPSESSID": session_id}, cookies=cookies_info)
html = BeautifulSoup(webpage.text)
form = html.find('form')
inputs = form.findAll('input')
names = []
for i in inputs:
names.append(i['name'])
How can I check immediately if the POST request I send is successful?
Check the status code of the response. It should be 200 for successful requests.
# Make the request
r = requests.post(submit_url,
params={"PHPSESSID": session_id},
files=parts,
cookies=cookies_info)
# Check the response code
if r.status_code == '200':
print "Submission successful!"
else:
print "Submission met a status code of: %s" % r.status_code

Post cookie data and return the value

I'm making a program that tries brute forcing a cookie value with python.
I'm working on an environment that is meant for IT-security students, it's like a CTF-as-a-service.
The mission i'm working on is a badly programmed login site that has a weak way of creating a cookie session.
The cookie consist of three values, an integer returned from the server side, the username, and a hash. I've already managed to acquire the username and hash, but i need to brute force the int value.
I have never done anything with cookies or tried to brute force them.
I was thinking i can manually observer the program running and returning the header of the site, until the content-length changes.
This is the code i have at the moment.
from requests import session
import Cookie
def createCook(salt):
#known atrributes for the cookie
salt = int('to_be_brute_forced')
user = str('user')
hash = str('hash_value')
# create the cookies
c = Cookie.SimpleCookie()
#assing cookie name(session) and values (s,u,h)
c['session'] = salt + user + hash
c['session']['domain'] = '127.0.0.1:7777'
c['session']['path'] = "/"
c['session']['expires'] = 1*1*3*60*60
print c
def Main():
print "Feed me Seymour: "
salt = 0
while (salt < 1000):
print 'this is the current cookie: ', createCook(salt)
cc = createCook(salt)
salt = salt + 1
try:
with session() as s:
s.post('http://127.0.0.1:7777/index.php', data=cc)
request = s.get('http://127.0.0.1:7777/index.php')
print request.headers
print request.text
except KeyboardInterrupt:
exit(0)
if __name__ == '__main__':
Main()
So my questions are:
1. Do i need to save the cookie before posting?
2. How do i always add +1 to the salt and recreate the cookie?
3. how do i post it to the site and know that the correct one is found?
While posting the request you have to use cookies as the argument instead of data
s.post(url, cookies=<cookiejar>)

Categories