Skip to content

Commit

Permalink
added Content-Type processing on add, removed old api web checking (h…
Browse files Browse the repository at this point in the history
…ence remove bs4), refactoring of all add methods, network now handles data/json cleanly, results returned based on Content-Type via new code, setup/requirements removed BeautifulSoup/bs4
  • Loading branch information
mahtin committed Dec 27, 2023
1 parent 91bd97d commit d6ae4ea
Show file tree
Hide file tree
Showing 8 changed files with 382 additions and 459 deletions.
202 changes: 102 additions & 100 deletions CloudFlare/api_decode_from_web.py
Original file line number Diff line number Diff line change
@@ -1,103 +1,105 @@
""" API extras for Cloudflare API"""

import sys
import datetime
# TODO - remove at some point

API_TYPES = ['GET', 'POST', 'PATCH', 'PUT', 'DELETE']

class mybs4():
""" mybs4 """

_BeautifulSoup = None
_Comment = None

def __init__(self):
""" __init__ """
pass

def _available(self):
""" _available() """
if not mybs4._BeautifulSoup:
try:
from bs4 import BeautifulSoup, Comment
mybs4._BeautifulSoup = BeautifulSoup
mybs4._Comment = Comment
self.Comment = mybs4._Comment
except ImportError:
return False
return True

def BeautifulSoup(self, content, parser):
""" BeautifulSoup() """
self._available()
return mybs4._BeautifulSoup(content, parser)

my_bs4 = mybs4()

def do_section(section):
""" API extras for Cloudflare API"""

cmds = []
# look for deprecated first in section
deprecated = False
deprecated_date = ''
deprecated_already = False
for tag2 in section.find_all('h3'):
# <h3 class="text-warning" data-reactid="13490">Deprecation Warning</h3>
if 'Deprecation Warning' in str(tag2):
deprecated = True
break
for tag2 in section.find_all('p'):
# <p class="deprecation-date" data-reactid="13491">End of life Date: November 2, 2020</p>
if 'End of life Date:' in str(tag2):
for child in tag2.children:
deprecated_date = str(child).replace('End of life Date:','').strip()
try:
# clean up date
d = datetime.datetime.strptime(deprecated_date, '%B %d, %Y')
if d <= datetime.datetime.now():
# already done!
deprecated_already = True
deprecated_date = d.strftime('%Y-%m-%d')
except ValueError:
# Lets not worry about all the date formats that could show-up. Leave as a string
pass
break
if deprecated_date != '':
break
# look for all API calls in section
for tag2 in section.find_all('pre'):
cmd = []
for child in tag2.children:
if isinstance(child, my_bs4.Comment):
# remove <!-- react-text ... -> parts
continue
cmd.append(str(child).strip())
if len(cmd) == 0:
continue
action = cmd[0]
if action == '' or action not in API_TYPES:
continue
cmd = ''.join(cmd[1:])
if cmd[0] != '/':
cmd = '/' + cmd
v = {'action': action, 'cmd': cmd, 'deprecated': deprecated, 'deprecated_date': deprecated_date, 'deprecated_already': deprecated_already}
cmds.append(v)
return cmds

def api_decode_from_web(content):
""" API extras for Cloudflare API"""

soup = my_bs4.BeautifulSoup(content, 'html.parser')

for child in soup.find_all('p'):
t = child.get_text()
if 'Last modified' in t:
sys.stderr.write("Retrieved API: %s\n" % (t.strip().replace('\n', ' ')))
break

all_cmds = []
for section in soup.find_all('section'):
all_cmds += do_section(section)

return sorted(all_cmds, key=lambda v: v['cmd'])
#import sys
#import datetime
#
#API_TYPES = ['GET', 'POST', 'PATCH', 'PUT', 'DELETE']
#
#class mybs4():
# """ mybs4 """
#
# _BeautifulSoup = None
# _Comment = None
#
# def __init__(self):
# """ __init__ """
# pass
#
# def _available(self):
# """ _available() """
# if not mybs4._BeautifulSoup:
# try:
# from bs4 import BeautifulSoup, Comment
# mybs4._BeautifulSoup = BeautifulSoup
# mybs4._Comment = Comment
# self.Comment = mybs4._Comment
# except ImportError:
# return False
# return True
#
# def BeautifulSoup(self, content, parser):
# """ BeautifulSoup() """
# self._available()
# return mybs4._BeautifulSoup(content, parser)
#
#my_bs4 = mybs4()
#
#def do_section(section):
# """ API extras for Cloudflare API"""
#
# cmds = []
# # look for deprecated first in section
# deprecated = False
# deprecated_date = ''
# deprecated_already = False
# for tag2 in section.find_all('h3'):
# # <h3 class="text-warning" data-reactid="13490">Deprecation Warning</h3>
# if 'Deprecation Warning' in str(tag2):
# deprecated = True
# break
# for tag2 in section.find_all('p'):
# # <p class="deprecation-date" data-reactid="13491">End of life Date: November 2, 2020</p>
# if 'End of life Date:' in str(tag2):
# for child in tag2.children:
# deprecated_date = str(child).replace('End of life Date:','').strip()
# try:
# # clean up date
# d = datetime.datetime.strptime(deprecated_date, '%B %d, %Y')
# if d <= datetime.datetime.now():
# # already done!
# deprecated_already = True
# deprecated_date = d.strftime('%Y-%m-%d')
# except ValueError:
# # Lets not worry about all the date formats that could show-up. Leave as a string
# pass
# break
# if deprecated_date != '':
# break
# # look for all API calls in section
# for tag2 in section.find_all('pre'):
# cmd = []
# for child in tag2.children:
# if isinstance(child, my_bs4.Comment):
# # remove <!-- react-text ... -> parts
# continue
# cmd.append(str(child).strip())
# if len(cmd) == 0:
# continue
# action = cmd[0]
# if action == '' or action not in API_TYPES:
# continue
# cmd = ''.join(cmd[1:])
# if cmd[0] != '/':
# cmd = '/' + cmd
# v = {'action': action, 'cmd': cmd, 'deprecated': deprecated, 'deprecated_date': deprecated_date, 'deprecated_already': deprecated_already}
# cmds.append(v)
# return cmds
#
#def api_decode_from_web(content):
# """ API extras for Cloudflare API"""
#
# soup = my_bs4.BeautifulSoup(content, 'html.parser')
#
# for child in soup.find_all('p'):
# t = child.get_text()
# if 'Last modified' in t:
# sys.stderr.write("Retrieved API: %s\n" % (t.strip().replace('\n', ' ')))
# break
#
# all_cmds = []
# for section in soup.find_all('section'):
# all_cmds += do_section(section)
#
# return sorted(all_cmds, key=lambda v: v['cmd'])
47 changes: 28 additions & 19 deletions CloudFlare/api_v4.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def zones(self):
self.add('AUTH', 'zones', 'custom_pages')
self.add('AUTH', 'zones', 'dns_records')
self.add('AUTH', 'zones', 'dns_records/export')
self.add('AUTH', 'zones', 'dns_records/import')
self.add('AUTH', 'zones', 'dns_records/import', content_type={'POST':'multipart/form-data'})
self.add('AUTH', 'zones', 'dns_records/scan')
self.add('VOID', 'zones', 'dns_settings')
self.add('AUTH', 'zones', 'dns_settings/use_apex_ns')
Expand Down Expand Up @@ -185,6 +185,15 @@ def zones_settings(self):
self.add('AUTH', 'zones', 'settings/waf')
self.add('AUTH', 'zones', 'settings/webp')
self.add('AUTH', 'zones', 'settings/websockets')
self.add('VOID', 'zones', 'settings/zaraz')
self.add('VOID', 'zones', 'settings/zaraz/v2')
self.add('AUTH', 'zones', 'settings/zaraz/v2/config')
self.add('AUTH', 'zones', 'settings/zaraz/v2/default')
self.add('AUTH', 'zones', 'settings/zaraz/v2/export')
self.add('AUTH', 'zones', 'settings/zaraz/v2/history')
self.add('AUTH', 'zones', 'settings/zaraz/v2/history/configs')
self.add('AUTH', 'zones', 'settings/zaraz/v2/publish')
self.add('AUTH', 'zones', 'settings/zaraz/v2/workflow')

def zones_analytics(self):
""" zones analytics """
Expand Down Expand Up @@ -399,7 +408,7 @@ def accounts(self):

self.add('VOID', 'accounts', 'dlp')
self.add('AUTH', 'accounts', 'dlp/datasets')
self.add('AUTH', 'accounts', 'dlp/datasets', 'upload')
self.add('AUTH', 'accounts', 'dlp/datasets', 'upload', content_type={'POST':'application/octet-stream'})
self.add('VOID', 'accounts', 'dlp/patterns')
self.add('AUTH', 'accounts', 'dlp/patterns/validate')
self.add('AUTH', 'accounts', 'dlp/payload_log')
Expand Down Expand Up @@ -448,7 +457,7 @@ def accounts(self):
self.add('AUTH', 'accounts', 'storage/kv/namespaces')
self.add('AUTH', 'accounts', 'storage/kv/namespaces', 'bulk')
self.add('AUTH', 'accounts', 'storage/kv/namespaces', 'keys')
self.add('AUTH', 'accounts', 'storage/kv/namespaces', 'values')
self.add('AUTH', 'accounts', 'storage/kv/namespaces', 'values', content_type={'PUT':'multipart/form-data'})
self.add('AUTH', 'accounts', 'storage/kv/namespaces', 'metadata')

self.add('AUTH', 'accounts', 'subscriptions')
Expand All @@ -458,9 +467,9 @@ def accounts(self):
self.add('VOID', 'accounts', 'vectorize')
self.add('AUTH', 'accounts', 'vectorize/index')
self.add('AUTH', 'accounts', 'vectorize/indexes')
self.add('AUTH', 'accounts', 'vectorize/indexes', 'insert')
self.add('AUTH', 'accounts', 'vectorize/indexes', 'insert', content_type={'POST':'application/x-ndjson'})
self.add('AUTH', 'accounts', 'vectorize/indexes', 'query')
self.add('AUTH', 'accounts', 'vectorize/indexes', 'upsert')
self.add('AUTH', 'accounts', 'vectorize/indexes', 'upsert', content_type={'POST':'application/x-ndjson'})

self.add('AUTH', 'accounts', 'virtual_dns')
self.add('VOID', 'accounts', 'virtual_dns', 'dns_analytics')
Expand All @@ -475,7 +484,7 @@ def accounts(self):
self.add('VOID', 'accounts', 'workers/dispatch')
self.add('AUTH', 'accounts', 'workers/dispatch/namespaces')
self.add('AUTH', 'accounts', 'workers/dispatch/namespaces', 'scripts')
self.add('AUTH', 'accounts', 'workers/dispatch/namespaces', 'scripts', 'content')
self.add('AUTH', 'accounts', 'workers/dispatch/namespaces', 'scripts', 'content', content_type={'PUT':'multipart/form-data'})
self.add('AUTH', 'accounts', 'workers/dispatch/namespaces', 'scripts', 'settings')
self.add('AUTH', 'accounts', 'workers/dispatch/namespaces', 'scripts', 'tags')
self.add('AUTH', 'accounts', 'workers/domains')
Expand All @@ -485,15 +494,15 @@ def accounts(self):
self.add('AUTH', 'accounts', 'workers/queues')
self.add('AUTH', 'accounts', 'workers/queues', 'consumers')
self.add('AUTH', 'accounts', 'workers/scripts')
self.add('AUTH', 'accounts', 'workers/scripts', 'content')
self.add('AUTH', 'accounts', 'workers/scripts', 'content', content_type={'PUT':'multipart/form-data'})
self.add('AUTH', 'accounts', 'workers/scripts', 'content/v2')
self.add('AUTH', 'accounts', 'workers/scripts', 'schedules')
self.add('AUTH', 'accounts', 'workers/scripts', 'settings')
self.add('AUTH', 'accounts', 'workers/scripts', 'settings', content_type={'PATCH':'multipart/form-data'})
self.add('AUTH', 'accounts', 'workers/scripts', 'tails')
self.add('AUTH', 'accounts', 'workers/scripts', 'usage-model')
self.add('VOID', 'accounts', 'workers/services')
self.add('VOID', 'accounts', 'workers/services', 'environments')
self.add('AUTH', 'accounts', 'workers/services', 'environments', 'content')
self.add('AUTH', 'accounts', 'workers/services', 'environments', 'content', content_type={'PUT':'multipart/form-data'})
self.add('AUTH', 'accounts', 'workers/services', 'environments', 'settings')
self.add('AUTH', 'accounts', 'workers/subdomain')

Expand All @@ -505,7 +514,7 @@ def accounts_addressing(self):
self.add('AUTH', 'accounts', 'addressing/address_maps', 'accounts')
self.add('AUTH', 'accounts', 'addressing/address_maps', 'ips')
self.add('AUTH', 'accounts', 'addressing/address_maps', 'zones')
self.add('AUTH', 'accounts', 'addressing/loa_documents')
self.add('AUTH', 'accounts', 'addressing/loa_documents', content_type={'POST':'multipart/form-data'})
self.add('AUTH', 'accounts', 'addressing/loa_documents', 'download')
self.add('AUTH', 'accounts', 'addressing/prefixes')
self.add('VOID', 'accounts', 'addressing/prefixes', 'bgp')
Expand Down Expand Up @@ -559,7 +568,7 @@ def accounts_stream(self):
self.add('AUTH', 'accounts', 'stream')
self.add('AUTH', 'accounts', 'stream', 'audio')
self.add('AUTH', 'accounts', 'stream', 'audio/copy')
self.add('AUTH', 'accounts', 'stream', 'captions')
self.add('AUTH', 'accounts', 'stream', 'captions', content_type={'PUT':'multipart/form-data'})
self.add('AUTH', 'accounts', 'stream', 'embed')
self.add('AUTH', 'accounts', 'stream', 'downloads')
self.add('AUTH', 'accounts', 'stream', 'token')
Expand All @@ -568,7 +577,7 @@ def accounts_stream(self):
self.add('AUTH', 'accounts', 'stream/direct_upload')
self.add('AUTH', 'accounts', 'stream/keys')
# self.add('AUTH', 'accounts', 'stream/preview')
self.add('AUTH', 'accounts', 'stream/watermarks')
self.add('AUTH', 'accounts', 'stream/watermarks', content_type={'POST':'multipart/form-data'})
self.add('AUTH', 'accounts', 'stream/webhook')
self.add('AUTH', 'accounts', 'stream/live_inputs')
self.add('AUTH', 'accounts', 'stream/live_inputs', 'outputs')
Expand Down Expand Up @@ -666,7 +675,7 @@ def accounts_extras(self):
""" extras """

self.add('VOID', 'accounts', 'ai')
self.add('AUTH', 'accounts', 'ai/run')
self.add('AUTH', 'accounts', 'ai/run', content_type={'POST':['application/json','application/octet-stream']})
self.add('AUTH', 'accounts', 'ai/run/proxy')

self.add('VOID', 'accounts', 'alerting')
Expand Down Expand Up @@ -737,14 +746,14 @@ def accounts_extras(self):
self.add('AUTH', 'accounts', 'gateway/rules')

self.add('VOID', 'accounts', 'images')
self.add('AUTH', 'accounts', 'images/v1')
self.add('AUTH', 'accounts', 'images/v1', content_type={'POST':'multipart/form-data'})
self.add('AUTH', 'accounts', 'images/v1', 'blob')
self.add('AUTH', 'accounts', 'images/v1/config')
self.add('AUTH', 'accounts', 'images/v1/keys')
self.add('AUTH', 'accounts', 'images/v1/stats')
self.add('AUTH', 'accounts', 'images/v1/variants')
self.add('AUTH', 'accounts', 'images/v2')
self.add('AUTH', 'accounts', 'images/v2/direct_upload')
self.add('AUTH', 'accounts', 'images/v2/direct_upload', content_type={'POST':'multipart/form-data'})

self.add('VOID', 'accounts', 'intel')
self.add('VOID', 'accounts', 'intel-phishing')
Expand All @@ -757,7 +766,7 @@ def accounts_extras(self):
self.add('AUTH', 'accounts', 'intel/domain/bulk')
self.add('AUTH', 'accounts', 'intel/indicator-feeds')
self.add('AUTH', 'accounts', 'intel/indicator-feeds', 'data')
self.add('AUTH', 'accounts', 'intel/indicator-feeds', 'snapshot')
self.add('AUTH', 'accounts', 'intel/indicator-feeds', 'snapshot', content_type={'PUT':'multipart/form-data'})
self.add('VOID', 'accounts', 'intel/indicator-feeds/permissions')
self.add('AUTH', 'accounts', 'intel/indicator-feeds/permissions/add')
self.add('AUTH', 'accounts', 'intel/indicator-feeds/permissions/remove')
Expand All @@ -776,7 +785,7 @@ def accounts_extras(self):

self.add('VOID', 'accounts', 'pages')
self.add('AUTH', 'accounts', 'pages/projects')
self.add('AUTH', 'accounts', 'pages/projects', 'deployments')
self.add('AUTH', 'accounts', 'pages/projects', 'deployments', content_type={'POST':'multipart/form-data'})
self.add('VOID', 'accounts', 'pages/projects', 'deployments', 'history')
self.add('AUTH', 'accounts', 'pages/projects', 'deployments', 'history/logs')
self.add('AUTH', 'accounts', 'pages/projects', 'deployments', 'retry')
Expand Down Expand Up @@ -845,7 +854,7 @@ def zones_extras(self):

self.add('VOID', 'zones', 'hostnames')
self.add('AUTH', 'zones', 'hostnames/settings')
self.add('AUTH', 'zones', 'snippets')
self.add('AUTH', 'zones', 'snippets', content_type={'PUT':'multipart/form-data'})
self.add('AUTH', 'zones', 'snippets', 'content')
self.add('AUTH', 'zones', 'snippets/snippet_rules')

Expand Down Expand Up @@ -907,7 +916,7 @@ def zones_api_gateway(self):
self.add('AUTH', 'zones', 'api_gateway/schemas')
self.add('VOID', 'zones', 'api_gateway/settings')
self.add('AUTH', 'zones', 'api_gateway/settings/schema_validation')
self.add('AUTH', 'zones', 'api_gateway/user_schemas')
self.add('AUTH', 'zones', 'api_gateway/user_schemas', content_type={'POST':'multipart/form-data'})
self.add('AUTH', 'zones', 'api_gateway/user_schemas', 'operations')


Expand Down
Loading

0 comments on commit d6ae4ea

Please sign in to comment.