connecting to mikrotik using routeros api - python-3.x

I am automating WiFi payments, so my code is able to ask for payments and a callback is sent. I get the information and save it, generate a user, send an sms to the client and create the generated user in mikrotik all at the same time.
Below is my code:
'''
def confirmation(request):
print("Start Mpesa")
global profile
mpesa_body = request.body.decode('utf-8')
mpesa_body = json.loads(mpesa_body)
print(mpesa_body)
print("Mpesa Body")
merchant_requestID = mpesa_body["Body"]["stkCallback"]["MerchantRequestID"]
print('merchant_requestID: ', merchant_requestID)
checkout_requestID = mpesa_body["Body"]["stkCallback"]["CheckoutRequestID"]
print('checkout_requestID: ', checkout_requestID)
result_code = mpesa_body["Body"]["stkCallback"]["ResultCode"]
print('result_code: ', result_code)
result_desc = mpesa_body["Body"]["stkCallback"]["ResultDesc"]
print('result_desc: ', result_desc)
metadata = mpesa_body["Body"]["stkCallback"]["CallbackMetadata"]["Item"]
for item in metadata:
title = item["Name"]
if title == "Amount":
amount = item["Value"]
print('Amount: ', amount)
elif title == "MpesaReceiptNumber":
mpesa_receipt_number = item["Value"]
print('Mpesa Reference No: ', mpesa_receipt_number)
elif title == "TransactionDate":
transaction_date = item["Value"]
print('Transaction date: ', transaction_date)
elif title == "PhoneNumber":
phone_number = item["Value"]
print('Phone Number: ', phone_number)
str_transaction_date = str(transaction_date)
trans_datetime = datetime.strptime(str_transaction_date, "%Y%m%d%H%M%S")
tz_trans_datetime = pytz.utc.localize(trans_datetime)
payment = MpesaPayment.objects.create(
MerchantRequestID=merchant_requestID,
CheckoutRequestID=checkout_requestID,
ResultCode=result_code,
ResultDesc=result_desc,
Amount=amount,
MpesaReceiptNumber=mpesa_receipt_number,
TransactionDate=tz_trans_datetime,
PhoneNumber=phone_number,
)
if result_code == 0:
payment.save()
print("Successfully saved")
password_length = 5
password = secrets.token_urlsafe(password_length)
print(password)
headers = {
'Content-Type': 'application/json',
'h_api_key': os.getenv("SMS_Token"),
'Accept': 'application/json'
}
payload = {
"mobile": phone_number,
"response_type": "json",
"sender_name": "23107",
"service_id": 0,
"message": "Your WiFi Voucher is " + password + ".\nAirRumi."
}
response = requests.request("POST", 'https://api.mobitechtechnologies.com/sms/sendsms', headers=headers,
json=payload)
r = response.json()
print(r)
print("SMS Sent")
print(amount)
if amount == 1:
profile = 'one_hour'
elif amount == 50:
profile = 'one_day'
elif amount == 300:
profile = 'one_week'
elif amount == 1000:
profile = 'one_month'
else:
print('Incorrect Amount')
print(profile)
connection = routeros_api.RouterOsApiPool(
host=os.getenv("ip"),
username=os.getenv("usernamee"),
password=os.getenv("password"),
port=8728,
use_ssl=False,
ssl_verify=False,
ssl_verify_hostname=True,
ssl_context=None,
plaintext_login=True
)
api = connection.get_api()
user = api.get_resource('/ip/hotspot/user')
user.add(name=password, server="hotspot1", password='1234', profile=profile)
print("User " + password + " created.")
else:
print("Payment was not successful")
context = {
"resultcode": result_code,
"resultdesc": result_desc
}
if context['resultcode'] == 0:
return JsonResponse(dict(context))
'''
I keep getting this error:
2023-01-03T13:37:23.849348+00:00 app[web.1]: Internal Server Error: /confirm
2023-01-03T13:37:23.849349+00:00 app[web.1]: Traceback (most recent call last):
2023-01-03T13:37:23.849350+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
2023-01-03T13:37:23.849350+00:00 app[web.1]: response = get_response(request)
2023-01-03T13:37:23.849353+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
2023-01-03T13:37:23.849353+00:00 app[web.1]: response = wrapped_callback(request, *callback_args, **callback_kwargs)
2023-01-03T13:37:23.849354+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
2023-01-03T13:37:23.849354+00:00 app[web.1]: return view_func(*args, **kwargs)
2023-01-03T13:37:23.849354+00:00 app[web.1]: File "/app/Splash/views.py", line 184, in confirmation
2023-01-03T13:37:23.849355+00:00 app[web.1]: api = connection.get_api()
2023-01-03T13:37:23.849355+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.10/site-packages/routeros_api/api.py", line 45, in get_api
2023-01-03T13:37:23.849355+00:00 app[web.1]: self.socket = api_socket.get_socket(self.host, self.port,
2023-01-03T13:37:23.849355+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.10/site-packages/routeros_api/api_socket.py", line 16, in get_socket
2023-01-03T13:37:23.849356+00:00 app[web.1]: api_socket.connect((hostname, port))
2023-01-03T13:37:23.849356+00:00 app[web.1]: TypeError: str, bytes or bytearray expected, not NoneType
2023-01-03T13:37:23.849807+00:00 app[web.1]: 10.1.14.110 - - [03/Jan/2023:13:37:23 +0000] "POST /confirm HTTP/1.1" 500 75776 "-" "Apache-HttpClient/4.5.5 (Java/1.8.0_251)"
2023-01-03T13:37:23.849768+00:00 heroku[router]: at=info method=POST path="/confirm" host=airrumi.herokuapp.com request_id=2cb1aad4-7a83-43ce-a942-005d2cf64be9 fwd="10.184.18.139,196.201.214.200" dyno=web.1 connect=0ms service=454ms status=500 bytes=76092 protocol=https
I have no idea where am messing up, because my test page is connecting perfectly and creating the user in mikrotik. Below is my test.py
'''
# generate usernames
import secrets
import os
import routeros_api
from dotenv import load_dotenv
load_dotenv()
password_length = 5
password = secrets.token_urlsafe(password_length)
print(password)
amount = 1
if amount == 1:
profile = 'one_hour'
elif amount == 50:
profile = 'one_day'
elif amount == 300:
profile = 'one_week'
elif amount == 1000:
profile = 'one_month'
else:
print('Incorrect Amount')
print(profile)
connection = routeros_api.RouterOsApiPool(
host=os.getenv("ip"),
username=os.getenv("usernamee"),
password=os.getenv("password"),
port=8728,
use_ssl=False,
ssl_verify=False,
ssl_verify_hostname=True,
ssl_context=None,
plaintext_login=True
)
api = connection.get_api()
user = api.get_resource('/ip/hotspot/user')
user.add(name=password, server="hotspot1", password='1234', profile=profile)
print("User " + password + " Created.")
'''

Related

Python passing a list of URL instead of one URL then output into excel file

I am trying to modify the code below to check the header URLs from a list
Usage
$ python securityheaders.py --max-redirects 5 https://secfault.fi
Output
Header 'x-xss-protection' is missing ... [ WARN ]
Header 'x-content-type-options' is missing ... [ WARN ]
Header 'content-security-policy' is missing ... [ WARN ]
Header 'x-powered-by' is missing ... [ OK ]
Header 'x-frame-options' contains value 'DENY' ... [ OK ]
Header 'strict-transport-security' contains value 'max-age=63072000' ... [ OK ]
Header 'access-control-allow-origin' is missing ... [ OK ]
Header 'server' contains value 'nginx/1.10.1' ... [ WARN ]
HTTPS supported ... [ OK ]
HTTPS valid certificate ... [ OK ]
HTTP -> HTTPS redirect ... [ OK ]
My question is the following:
Instead of passing one URL as argument like the usage above, is it possible to pass a list of URL to check the header and then save the result into the excel file like below.
Which part of the code should I modify?
Any help would be much appreciated
Thank you for reading
Desire ouput
Code
Source code
import http.client
import argparse
import socket
import ssl
import sys
import re
from urllib.parse import urlparse
class SecurityHeaders():
def __init__(self):
pass
def evaluate_warn(self, header, contents):
""" Risk evaluation function.
Set header warning flag (1/0) according to its contents.
Args:
header (str): HTTP header name in lower-case
contents (str): Header contents (value)
"""
warn = 1
if header == 'x-frame-options':
if contents.lower() in ['deny', 'sameorigin']:
warn = 0
else:
warn = 1
if header == 'strict-transport-security':
warn = 0
""" Evaluating the warn of CSP contents may be a bit more tricky.
For now, just disable the warn if the header is defined
"""
if header == 'content-security-policy':
warn = 0
""" Raise the warn flag, if cross domain requests are allowed from any
origin """
if header == 'access-control-allow-origin':
if contents == '*':
warn = 1
else:
warn = 0
if header.lower() == 'x-xss-protection':
if contents.lower() in ['1', '1; mode=block']:
warn = 0
else:
warn = 1
if header == 'x-content-type-options':
if contents.lower() == 'nosniff':
warn = 0
else:
warn =1
""" Enable warning if backend version information is disclosed """
if header == 'x-powered-by' or header == 'server':
if len(contents) > 1:
warn = 1
else:
warn = 0
return {'defined': True, 'warn': warn, 'contents': contents}
def test_https(self, url):
parsed = urlparse(url)
protocol = parsed[0]
hostname = parsed[1]
path = parsed[2]
sslerror = False
conn = http.client.HTTPSConnection(hostname, context = ssl.create_default_context() )
try:
conn.request('GET', '/')
res = conn.getresponse()
except socket.gaierror:
return {'supported': False, 'certvalid': False}
except ssl.CertificateError:
return {'supported': True, 'certvalid': False}
except:
sslerror = True
# if tls connection fails for unexcepted error, retry without verifying cert
if sslerror:
conn = http.client.HTTPSConnection(hostname, timeout=5, context = ssl._create_stdlib_context() )
try:
conn.request('GET', '/')
res = conn.getresponse()
return {'supported': True, 'certvalid': False}
except:
return {'supported': False, 'certvalid': False}
return {'supported': True, 'certvalid': True}
def test_http_to_https(self, url, follow_redirects = 5):
parsed = urlparse(url)
protocol = parsed[0]
hostname = parsed[1]
path = parsed[2]
if not protocol:
protocol = 'http' # default to http if protocl scheme not specified
if protocol == 'https' and follow_redirects != 5:
return True
elif protocol == 'https' and follow_redirects == 5:
protocol = 'http'
if (protocol == 'http'):
conn = http.client.HTTPConnection(hostname)
try:
conn.request('HEAD', path)
res = conn.getresponse()
headers = res.getheaders()
except socket.gaierror:
print('HTTP request failed')
return False
""" Follow redirect """
if (res.status >= 300 and res.status < 400 and follow_redirects > 0):
for header in headers:
if (header[0].lower() == 'location'):
return self.test_http_to_https(header[1], follow_redirects - 1)
return False
def check_headers(self, url, follow_redirects = 0):
""" Make the HTTP request and check if any of the pre-defined
headers exists.
Args:
url (str): Target URL in format: scheme://hostname/path/to/file
follow_redirects (Optional[str]): How deep we follow the redirects,
value 0 disables redirects.
"""
""" Default return array """
retval = {
'x-frame-options': {'defined': False, 'warn': 1, 'contents': '' },
'strict-transport-security': {'defined': False, 'warn': 1, 'contents': ''},
'access-control-allow-origin': {'defined': False, 'warn': 0, 'contents': ''},
'content-security-policy': {'defined': False, 'warn': 1, 'contents': ''},
'x-xss-protection': {'defined': False, 'warn': 1, 'contents': ''},
'x-content-type-options': {'defined': False, 'warn': 1, 'contents': ''},
'x-powered-by': {'defined': False, 'warn': 0, 'contents': ''},
'server': {'defined': False, 'warn': 0, 'contents': ''}
}
parsed = urlparse(url)
protocol = parsed[0]
hostname = parsed[1]
path = parsed[2]
if (protocol == 'http'):
conn = http.client.HTTPConnection(hostname)
elif (protocol == 'https'):
# on error, retry without verifying cert
# in this context, we're not really interested in cert validity
ctx = ssl._create_stdlib_context()
conn = http.client.HTTPSConnection(hostname, context = ctx )
else:
""" Unknown protocol scheme """
return {}
try:
conn.request('HEAD', path)
res = conn.getresponse()
headers = res.getheaders()
except socket.gaierror:
print('HTTP request failed')
return False
""" Follow redirect """
if (res.status >= 300 and res.status < 400 and follow_redirects > 0):
for header in headers:
if (header[0].lower() == 'location'):
redirect_url = header[1]
if not re.match('^https?://', redirect_url):
redirect_url = protocol + '://' + hostname + redirect_url
return self.check_headers(redirect_url, follow_redirects - 1)
""" Loop through headers and evaluate the risk """
for header in headers:
#set to lowercase before the check
headerAct = header[0].lower()
if (headerAct in retval):
retval[headerAct] = self.evaluate_warn(headerAct, header[1])
return retval
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Check HTTP security headers', \
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('url', metavar='URL', type=str, help='Target URL')
parser.add_argument('--max-redirects', dest='max_redirects', metavar='N', default=2, type=int, help='Max redirects, set 0 to disable')
args = parser.parse_args()
url = args.url
redirects = args.max_redirects
foo = SecurityHeaders()
parsed = urlparse(url)
if not parsed.scheme:
url = 'http://' + url # default to http if scheme not provided
headers = foo.check_headers(url, redirects)
if not headers:
print ("Failed to fetch headers, exiting...")
sys.exit(1)
okColor = '\033[92m'
warnColor = '\033[93m'
endColor = '\033[0m'
for header, value in headers.items():
if value['warn'] == 1:
if value['defined'] == False:
print('Header \'' + header + '\' is missing ... [ ' + warnColor + 'WARN' + endColor + ' ]')
else:
print('Header \'' + header + '\' contains value \'' + value['contents'] + '\'' + \
' ... [ ' + warnColor + 'WARN' + endColor + ' ]')
elif value['warn'] == 0:
if value['defined'] == False:
print('Header \'' + header + '\' is missing ... [ ' + okColor + 'OK' + endColor +' ]')
else:
print('Header \'' + header + '\' contains value \'' + value['contents'] + '\'' + \
' ... [ ' + okColor + 'OK' + endColor + ' ]')
https = foo.test_https(url)
if https['supported']:
print('HTTPS supported ... [ ' + okColor + 'OK' + endColor + ' ]')
else:
print('HTTPS supported ... [ ' + warnColor + 'FAIL' + endColor + ' ]')
if https['certvalid']:
print('HTTPS valid certificate ... [ ' + okColor + 'OK' + endColor + ' ]')
else:
print('HTTPS valid certificate ... [ ' + warnColor + 'FAIL' + endColor + ' ]')
if foo.test_http_to_https(url, 5):
print('HTTP -> HTTPS redirect ... [ ' + okColor + 'OK' + endColor + ' ]')
else:
print('HTTP -> HTTPS redirect ... [ ' + warnColor + 'FAIL' + endColor + ' ]')

I want to know how to read the value of headers in SetTask class after configuring tasks = [SetTask]?

from locust import HttpUser, task, between,SequentialTaskSet,TaskSet,User,events
import json
#events.test_start.add_listener
def on_start(**kwargs):
print("A test will start...")
#events.test_stop.add_listener
def on_stop(**kwargs):
print("A test is ending...")
class SetTask(TaskSet):
#task
def getLogDetail(self):
deatil_url = "/auth/online?page=0&size=10&sort=id%2Cdesc"
with self.client.request(method='GET',
url=deatil_url,
headers=self.headers,
name='get log detail') as response:
print(response.text)
class FlaskTask(SequentialTaskSet):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
def on_start(self):
res = self.client.request(method='GET', url="/auth/code",name="get code")
uuid = res.json()['uuid']
headers = {
"content-type": "application/json;charset=UTF-8",
}
datda_info = {
"code": "8",
"password": "B0GdcVWB+XtTwsyBjzoRkn8VnSgtPVKpl8mp7AuQ+BTeU030grUkRwmOHXFCjEhKXB7yezBS7dFEJ63ykR2piQ==",
"username": "admin",
"uuid": uuid
}
with self.client.request(method='POST',url="/auth/login", headers=headers, catch_response=True,data=json.dumps(datda_info),name="get token") as response:
self.token = response.json()['token']
if response.status_code == 200:
self.token = response.json()['token']
response.success()
else:
response.failure("get token failed")
self.headers = {
"Authorization": self.token
}
tasks = [SetTask]
#task
def getUserDetail(self):
deatil_url = "/api/dictDetail?dictName=user_status&page=0&size=9999"
with self.client.request(method='GET',
url=deatil_url,
headers=self.headers,
name='get user detail') as response:
print(response.text)
def function_task():
print("This is the function task")
class FlaskUser(HttpUser):
host = 'http://192.168.31.243:8888'
wait_time = between(1,3)
tasks = [FlaskTask,function_task]
I got error:
A test will start...
[2022-03-26 00:04:56,146] wangguilin/INFO/locust.runners: Ramping to 1 users at a rate of 1.00 per second
[2022-03-26 00:04:56,147] wangguilin/INFO/locust.runners: All users spawned: {"FlaskUser": 1} (1 total users)
[2022-03-26 00:04:56,148] wangguilin/ERROR/locust.user.task: function_task() takes 0 positional arguments but 1 was given
Traceback (most recent call last):
File "c:\users\Users\pycharmprojects\testlocust\venv\lib\site-packages\locust\user\task.py", line 319, in run
self.execute_next_task()
File "c:\users\Users\pycharmprojects\testlocust\venv\lib\site-packages\locust\user\task.py", line 344, in execute_next_task
self.execute_task(self._task_queue.pop(0))
File "c:\users\Users\pycharmprojects\testlocust\venv\lib\site-packages\locust\user\task.py", line 457, in execute_task
task(self.user)
TypeError: function_task() takes 0 positional arguments but 1 was given
[2022-03-26 00:04:58,154] wangguilin/ERROR/locust.user.task: 'SetTask' object has no attribute 'headers'
Traceback (most recent call last):
File "c:\users\Users\pycharmprojects\testlocust\venv\lib\site-packages\locust\user\task.py", line 319, in run
self.execute_next_task()
File "c:\users\Users\pycharmprojects\testlocust\venv\lib\site-packages\locust\user\task.py", line 344, in execute_next_task
self.execute_task(self._task_queue.pop(0))
File "c:\users\Users\pycharmprojects\testlocust\venv\lib\site-packages\locust\user\task.py", line 356, in execute_task
task(self)
File "C:\Users\Users\PycharmProjects\testlocust\locustflask.py", line 22, in getLogDetail
headers=self.headers,
AttributeError: 'SetTask' object has no attribute 'headers'
Traceback (most recent call last):
File "c:\users\Users\pycharmprojects\testlocust\venv\lib\site-packages\gevent_ffi\loop.py", line 270, in python_check_callback
def python_check_callback(self, watcher_ptr): # pylint:disable=unused-argument
question:
I want to know how to read the value of headers in SetTask class after configuring tasks = [SetTask]?
my locust version is: 2.8.3
So can parameters be passed in this case?

Flask - TypeError: Object of type cycle is not JSON serializable

I'm trying to return a json response from server to client after client makes a post via AJAX.
Like this, it works:
#app.route("/test", methods=["GET", "POST"])
#login_required
def test():
if request.is_xhr:
try:
json_response = {
"result": "success"
}
except Exception as e:
err = _except(line=sys.exc_info()[-1].tb_lineno, error=e, function_name=what_func(), script_name=__file__)
json_response = {"result": "failure", "msg": err}
return jsonify(json_response)
else:
return redirect("/not-found")
return ''
If I do like this, it doesn't works:
#app.route("/test", methods=["GET", "POST"])
#login_required
def test():
if request.is_xhr:
try:
_dict = {
"key1": "value1",
"key2": "value2"
}
if not "my_dict" in session:
session["my_dict"] = [_dict]
else:
session["my_dict"] = session["my_dict"] + [_dict]
session.modified = True
json_response = {
"result": "success"
}
except Exception as e:
err = _except(line=sys.exc_info()[-1].tb_lineno, error=e, function_name=what_func(), script_name=__file__)
json_response = {"result": "failure", "msg": err}
return jsonify(json_response)
else:
return redirect("/not-found")
return ''
I get the following error and client doesn't receives json response:
File "~/myprojectenv/lib/python3.8/site-packages/flask/json/__init__.py", line 100, in default
return _json.JSONEncoder.default(self, o)
File "/usr/lib/python3.8/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type cycle is not JSON serializable
[2020-09-26 19:01:14,091] ERROR in app: Request finalizing failed with an error while handling an error
If I remove that stretch:
if not "my_dict" in session:
session["my_dict"] = [_dict]
else:
session["my_dict"] = session["my_dict"] + [_dict]
session.modified = True
It works again. Client receives json response.
I figured out the trouble.
Check out the following function:
#app.route("/test", methods=["GET", "POST"])
def test():
if request.is_xhr:
try:
licycle = cycle(files)
nextelem = next(licycle)
_dict = {
"sid": session["_id"],
"licycle": licycle,
"nextelem": nextelem,
"licycle2": licycle2,
"nextelem2": nextelem2,
"mon_id": _id,
"sch_id": 0
}
if not "all_submons" in session:
session["all_submons"] = [_dict]
else:
session["all_submons"] = session["all_submons"] + [_dict]
session.modified = True
all_submons.setdefault("sub_mons", []).append(_dict)
json_response = {"result": "success"}
except Exception as e:
err = _except(line=sys.exc_info()[-1].tb_lineno, error=e, function_name=what_func(), script_name=__file__)
json_response = {"result": "failure", "err": err}
finally:
try:
print("exiting...")
except Exception as e:
pass
return jsonify(json_response)
else:
return redirect("/not-found")
return ""
The reason is that type of licycle variable is <class 'itertools.cycle'> and session "probably doesn't accepts" that type of variable like a dictionary accepts as you can see in my all_submons dict variable.
The point is:
The execution DOESN'T FALLS in exception. And _dict is stored on session as you can see to next.
print(f"Session before: {session}")
print(f"all_submons before: {all_submons}")
if not "all_submons" in session:
session["all_submons"] = [_dict]
else:
session["all_submons"] = session["all_submons"] + [_dict]
session.modified = True
all_submons.setdefault("sub_mons", []).append(_dict)
print(f"Session after: {session}")
print(f"all_submons after: {all_submons}\n")
You can check the output:
Session before: <SecureCookieSession {'_fresh': True, '_id': 'e253a950...', 'all_submons': [], 'user_id': '1'}>
all_submons before: {}
Session after: <SecureCookieSession {'_fresh': True, '_id': 'e253a...', 'all_submons': [{'sid': 'e253a95...', 'licycle': <itertools.cycle object at 0x7fc989237280>, 'nextelem': ('1a4add0f275c7275.jpg',), 'licycle2': None, 'nextelem2': None, 'mon_id': 1, 'sch_id': 0}], 'user_id': '1'}>
all_submons after: {'sub_mons': [{'sid': 'e253a...', 'licycle': <itertools.cycle object at 0x7fd6f1a17b80>, 'nextelem': ('1a4add0f275c7275.jpg',), 'licycle2': None, 'nextelem2': None, 'mon_id': 1, 'sch_id': 0}]}
I'm not sure about session "probably doesn't accepts" that type of variable - <class 'itertools.cycle'>
But I created other dictionary with others variables, without type of itertools.cycle and it worked.

Not able to upload file using slack api files.upload

This question may seem duplicate but I have tried a lot but did not get success.
I am trying to upload html file using https://slack.com/api/files.upload API but I am getting below error always.
response
{'ok': False, 'error': 'no_file_data'}
I went through documentation [a link]https://api.slack.com/methods/files.upload and tried with different options but still i am getting the same response {'ok': False, 'error': 'no_file_data'}
Also i have seen many similar questions in stack overflow but none of them resolved the problem.
[a link]no_file_data error when using Slack API upload
[a link]How to upload files to slack using file.upload and requests
Below is my code.
import requests
def post_reports_to_slack(html_report):
"""
"""
url = "https://slack.com/api/files.upload"
# my_file = {html_report, open(html_report, 'rb'), 'html'}
data = {
"token": bot_user_token,
"channels": channel_name,
"file": html_report,
"filetype": "html"
}
# data = "token=" + bot_user_token + \
# "&channels=" + channel_name +\
# "&file=" + html_report + "&filetype=" + "html"
response = requests.post(
url=url, data=data,
headers={"Content-Type": "application/x-www-form-urlencoded"})
print("response", response)
print(response.json())
if response.status_code == 200:
print("successfully completed post_reports_to_slack "
"and status code %s" % response.status_code)
else:
print("Failed to post report on slack channel "
"and status code %s" % response.status_code)
Please help to resolve the issue.
I was needed to add "content" argument and "filename" argument instead of "file" argument in files.upload API payload, Now file uploading to slack channel is working fine.
import requests
def post_reports_to_slack(html_report):
url = "https://slack.com/api/files.upload"
with open(html_report) as fh:
html_data = fh.read()
data = {
"token": bot_user_token,
"channels": "#channel_name",
"content": html_data,
"filename": "report.html",
"filetype": "html",
}
response = requests.post(
url=url, data=data,
headers={"Content-Type": "application/x-www-form-urlencoded"})
if response.status_code == 200:
print("successfully completed post_reports_to_slack "
"and status code %s" % response.status_code)
else:
print("Failed to post report on slack channel "
"and status code %s" % response.status_code)

Google Adwords Traffic Estimator Service and Python

I've downloaded a code sample that looks for particular keywords and pulls some metrics. I've noticed a lot of Google Adwords API examples are compliant with python 3.x so I'm wondering if there is an issue with that? See below for code sample:
from googleads import adwords
def main(client):
# Initialize appropriate service.
traffic_estimator_service = client.GetService(
'TrafficEstimatorService', version='v201609')
# Construct selector object and retrieve traffic estimates.
keywords = [
{'text': 'mars cruise', 'matchType': 'BROAD'},
{'text': 'cheap cruise', 'matchType': 'PHRASE'},
{'text': 'cruise', 'matchType': 'EXACT'}
]
negative_keywords = [
{'text': 'moon walk', 'matchType': 'BROAD'}
]
keyword_estimate_requests = []
for keyword in keywords:
keyword_estimate_requests.append({
'keyword': {
'xsi_type': 'Keyword',
'matchType': keyword['matchType'],
'text': keyword['text']
}
})
for keyword in negative_keywords:
keyword_estimate_requests.append({
'keyword': {
'xsi_type': 'Keyword',
'matchType': keyword['matchType'],
'text': keyword['text']
},
'isNegative': 'true'
})
# Create ad group estimate requests.
adgroup_estimate_requests = [{
'keywordEstimateRequests': keyword_estimate_requests,
'maxCpc': {
'xsi_type': 'Money',
'microAmount': '1000000'
}
}]
# Create campaign estimate requests.
campaign_estimate_requests = [{
'adGroupEstimateRequests': adgroup_estimate_requests,
'criteria': [
{
'xsi_type': 'Location',
'id': '2840' # United States.
},
{
'xsi_type': 'Language',
'id': '1000' # English.
}
],
}]
# Create the selector.
selector = {
'campaignEstimateRequests': campaign_estimate_requests,
}
# Optional: Request a list of campaign-level estimates segmented by
# platform.
selector['platformEstimateRequested'] = True
# Get traffic estimates.
estimates = traffic_estimator_service.get(selector)
campaign_estimate = estimates['campaignEstimates'][0]
# Display the campaign level estimates segmented by platform.
if 'platformEstimates' in campaign_estimate:
platform_template = ('Results for the platform with ID: "%d" and name: '
'"%s".')
for platform_estimate in campaign_estimate['platformEstimates']:
platform = platform_estimate['platform']
DisplayEstimate(platform_template % (platform['id'],
platform['platformName']),
platform_estimate['minEstimate'],
platform_estimate['maxEstimate'])
# Display the keyword estimates.
if 'adGroupEstimates' in campaign_estimate:
ad_group_estimate = campaign_estimate['adGroupEstimates'][0]
if 'keywordEstimates' in ad_group_estimate:
keyword_estimates = ad_group_estimate['keywordEstimates']
keyword_template = ('Results for the keyword with text "%s" and match '
'type "%s":')
keyword_estimates_and_requests = zip(keyword_estimates,
keyword_estimate_requests)
for keyword_tuple in keyword_estimates_and_requests:
if keyword_tuple[1].get('isNegative', False):
continue
keyword = keyword_tuple[1]['keyword']
keyword_estimate = keyword_tuple[0]
DisplayEstimate(keyword_template % (keyword['text'],
keyword['matchType']),
keyword_estimate['min'], keyword_estimate['max'])
def _CalculateMean(min_est, max_est):
if min_est and max_est:
return (float(min_est) + float(max_est)) / 2.0
else:
return None
def _FormatMean(mean):
if mean:
return '%.2f' % mean
else:
return 'N/A'
def DisplayEstimate(message, min_estimate, max_estimate):
"""Displays mean average cpc, position, clicks, and total cost for estimate.
Args:
message: str message to display for the given estimate.
min_estimate: sudsobject containing a minimum estimate from the
TrafficEstimatorService response.
max_estimate: sudsobject containing a maximum estimate from the
TrafficEstimatorService response.
"""
# Find the mean of the min and max values.
mean_avg_cpc = (_CalculateMean(min_estimate['averageCpc']['microAmount'],
max_estimate['averageCpc']['microAmount'])
if 'averageCpc' in min_estimate else None)
mean_avg_pos = (_CalculateMean(min_estimate['averagePosition'],
max_estimate['averagePosition'])
if 'averagePosition' in min_estimate else None)
mean_clicks = _CalculateMean(min_estimate['clicksPerDay'],
max_estimate['clicksPerDay'])
mean_total_cost = _CalculateMean(min_estimate['totalCost']['microAmount'],
max_estimate['totalCost']['microAmount'])
print (message)
print ('Estimated average CPC: %s' % _FormatMean(mean_avg_cpc))
print ('Estimated ad position: %s' % _FormatMean(mean_avg_pos))
print ('Estimated daily clicks: %s' % _FormatMean(mean_clicks))
print ('Estimated daily cost: %s' % _FormatMean(mean_total_cost))
if __name__ == '__main__':
# Initialize client object.
adwords_client = adwords.AdWordsClient.LoadFromStorage()
main(adwords_client)
Here is the error message:
(Money) not-found
path: "Money", not-found
(Keyword) not-found
path: "Keyword", not-found
(Keyword) not-found
path: "Keyword", not-found
(Keyword) not-found
path: "Keyword", not-found
(Keyword) not-found
path: "Keyword", not-found
(Location) not-found
path: "Location", not-found
(Language) not-found
path: "Language", not-found
<suds.sax.document.Document object at 0x03BF1D10>
Server raised fault in response.
Traceback (most recent call last):
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\transport\http.py", line 82, in send
fp = self.u2open(u2request)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\transport\http.py", line 132, in u2open
return url.open(u2request, timeout=tm)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 472, in open
response = meth(req, response)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 582, in http_response
'http', request, response, code, msg, hdrs)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 510, in error
return self._call_chain(*args)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 444, in _call_chain
result = func(*args)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 590, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 500: Internal Server Error
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\client.py", line 613, in send
reply = self.options.transport.send(request)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\transport\http.py", line 94, in send
raise TransportError(e.msg, e.code, e.fp)
suds.transport.TransportError: Internal Server Error
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\adwords test - Copy (2).py", line 177, in <module>
main(adwords_client)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\adwords test - Copy (2).py", line 95, in main
estimates = traffic_estimator_service.get(selector)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\googleads\common.py", line 696, in MakeSoapRequest
raise e
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\googleads\common.py", line 692, in MakeSoapRequest
for arg in args])
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\client.py", line 521, in __call__
return client.invoke(args, kwargs)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\client.py", line 581, in invoke
result = self.send(soapenv)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\client.py", line 619, in send
description=tostr(e), original_soapenv=original_soapenv)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\client.py", line 670, in process_reply
raise WebFault(fault, replyroot)
suds.WebFault: Server raised fault: '[AuthenticationError.CLIENT_CUSTOMER_ID_IS_REQUIRED # ; trigger:'<null>']'
You should set client_customer_id in your googleads.yaml file . you can get client_customer_id from your manager account. go to your manager account and add client then copy your id from upright corner of screen. in googleads.yaml file paste that id to client_customer_id .

Resources