mirror of
https://github.com/FranP-code/public-apis.git
synced 2025-10-13 00:03:04 +00:00
Remove old scripts
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
# Argument validation
|
||||
if [ $# -ne 3 ]; then
|
||||
echo "Usage: $0 <github-repo> <pull-number> <format-file>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Assign variables
|
||||
GITHUB_REPOSITORY="$1"
|
||||
GITHUB_PULL_REQUEST="$2"
|
||||
FORMAT_FILE="$3"
|
||||
|
||||
# Move to root of project
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
|
||||
# Determine files
|
||||
FORMAT_FILE="$( realpath "${FORMAT_FILE}" )"
|
||||
|
||||
# Skip if build number could not be determined
|
||||
if [ -z "$GITHUB_REPOSITORY" -o -z "$GITHUB_PULL_REQUEST" ]; then
|
||||
echo "No pull request and/or repository is provided"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Pull changes on PR
|
||||
echo "running on Pull Request #$GITHUB_PULL_REQUEST"
|
||||
|
||||
# Trick the URL validator python script into not seeing this as a URL
|
||||
DUMMY_SCHEME="https"
|
||||
DIFF_URL="$DUMMY_SCHEME://patch-diff.githubusercontent.com/raw/$GITHUB_REPOSITORY/pull/$GITHUB_PULL_REQUEST.diff"
|
||||
curl -L -o diff.txt "$DIFF_URL"
|
||||
|
||||
# Construct diff
|
||||
echo "------- BEGIN DIFF -------"
|
||||
cat diff.txt
|
||||
echo "-------- END DIFF --------"
|
||||
cat diff.txt | egrep "\+" > additions.txt
|
||||
|
||||
echo "------ BEGIN ADDITIONS -----"
|
||||
cat additions.txt
|
||||
echo "------- END ADDITIONS ------"
|
||||
LINK_FILE=additions.txt
|
||||
|
||||
# Validate links
|
||||
echo "Running link validation..."
|
||||
./build/validate_links.py "$LINK_FILE"
|
||||
|
||||
# Vebosity
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "link validation failed!"
|
||||
exit 1
|
||||
else
|
||||
echo "link validation passed!"
|
||||
fi
|
||||
@@ -1,2 +0,0 @@
|
||||
flake8>=3.5.0
|
||||
httplib2==0.19.0
|
||||
@@ -1,168 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
anchor = '###'
|
||||
min_entries_per_section = 3
|
||||
auth_keys = ['apiKey', 'OAuth', 'X-Mashape-Key', 'No', 'User-Agent']
|
||||
punctuation = ['.', '?', '!']
|
||||
https_keys = ['Yes', 'No']
|
||||
cors_keys = ['Yes', 'No', 'Unknown']
|
||||
|
||||
index_title = 0
|
||||
index_desc = 1
|
||||
index_auth = 2
|
||||
index_https = 3
|
||||
index_cors = 4
|
||||
index_link = 5
|
||||
num_segments = 5
|
||||
|
||||
errors = []
|
||||
title_links = []
|
||||
anchor_re = re.compile(anchor + '\s(.+)')
|
||||
section_title_re = re.compile('\*\s\[(.*)\]')
|
||||
link_re = re.compile('\[(.+)\]\((http.*)\)')
|
||||
|
||||
|
||||
def add_error(line_num, message):
|
||||
"""adds an error to the dynamic error list"""
|
||||
err = '(L{:03d}) {}'.format(line_num + 1, message)
|
||||
errors.append(err)
|
||||
|
||||
|
||||
def check_alphabetical(lines):
|
||||
"""
|
||||
checks if all entries per section are in alphabetical order based in entry title
|
||||
"""
|
||||
sections = {}
|
||||
section_line_num = {}
|
||||
for line_num, line in enumerate(lines):
|
||||
if line.startswith(anchor):
|
||||
category = line.split(anchor)[1].strip()
|
||||
sections[category] = []
|
||||
section_line_num[category] = line_num
|
||||
continue
|
||||
if not line.startswith('|') or line.startswith('|---'):
|
||||
continue
|
||||
raw_title = [x.strip() for x in line.split('|')[1:-1]][0]
|
||||
title_re_match = link_re.match(raw_title)
|
||||
if title_re_match:
|
||||
sections[category].append(title_re_match.group(1).upper())
|
||||
|
||||
for category, entries in sections.items():
|
||||
if sorted(entries) != entries:
|
||||
add_error(section_line_num[category], "{} section is not in alphabetical order".format(category))
|
||||
|
||||
|
||||
def check_entry(line_num, segments):
|
||||
# START Title
|
||||
raw_title = segments[index_title]
|
||||
title_re_match = link_re.match(raw_title)
|
||||
# url should be wrapped in '[TITLE](LINK)' Markdown syntax
|
||||
if not title_re_match:
|
||||
add_error(line_num, 'Title syntax should be "[TITLE](LINK)"')
|
||||
else:
|
||||
# do not allow "... API" in the entry title
|
||||
title = title_re_match.group(1)
|
||||
if title.upper().endswith(' API'):
|
||||
add_error(line_num, 'Title should not end with "... API". Every entry is an API here!')
|
||||
# END Title
|
||||
# START Description
|
||||
# first character should be capitalized
|
||||
char = segments[index_desc][0]
|
||||
if char.upper() != char:
|
||||
add_error(line_num, "first character of description is not capitalized")
|
||||
# last character should not punctuation
|
||||
char = segments[index_desc][-1]
|
||||
if char in punctuation:
|
||||
add_error(line_num, "description should not end with {}".format(char))
|
||||
desc_length = len(segments[index_desc])
|
||||
if desc_length > 100:
|
||||
add_error(line_num, "description should not exceed 100 characters (currently {})".format(desc_length))
|
||||
# END Description
|
||||
# START Auth
|
||||
# values should conform to valid options only
|
||||
auth = segments[index_auth]
|
||||
if auth != 'No' and (not auth.startswith('`') or not auth.endswith('`')):
|
||||
add_error(line_num, "auth value is not enclosed with `backticks`")
|
||||
if auth.replace('`', '') not in auth_keys:
|
||||
add_error(line_num, "{} is not a valid Auth option".format(auth))
|
||||
# END Auth
|
||||
# START HTTPS
|
||||
# values should conform to valid options only
|
||||
https = segments[index_https]
|
||||
if https not in https_keys:
|
||||
add_error(line_num, "{} is not a valid HTTPS option".format(https))
|
||||
# END HTTPS
|
||||
# START CORS
|
||||
# values should conform to valid options only
|
||||
cors = segments[index_cors]
|
||||
if cors not in cors_keys:
|
||||
add_error(line_num, "{} is not a valid CORS option".format(cors))
|
||||
# END CORS
|
||||
|
||||
|
||||
def check_format(filename):
|
||||
"""
|
||||
validates that each line is formatted correctly,
|
||||
appending to error list as needed
|
||||
"""
|
||||
with open(filename) as fp:
|
||||
lines = list(line.rstrip() for line in fp)
|
||||
check_alphabetical(lines)
|
||||
# START Check Entries
|
||||
num_in_category = min_entries_per_section + 1
|
||||
category = ""
|
||||
category_line = 0
|
||||
for line_num, line in enumerate(lines):
|
||||
if section_title_re.match(line):
|
||||
title_links.append(section_title_re.match(line).group(1))
|
||||
# check each section for the minimum number of entries
|
||||
if line.startswith(anchor):
|
||||
match = anchor_re.match(line)
|
||||
if match:
|
||||
if match.group(1) not in title_links:
|
||||
add_error(line_num, "section header ({}) not added as a title link".format(match.group(1)))
|
||||
else:
|
||||
add_error(line_num, "section header is not formatted correctly")
|
||||
if num_in_category < min_entries_per_section:
|
||||
add_error(category_line, "{} section does not have the minimum {} entries (only has {})".format(
|
||||
category, min_entries_per_section, num_in_category))
|
||||
category = line.split(' ')[1]
|
||||
category_line = line_num
|
||||
num_in_category = 0
|
||||
continue
|
||||
# skips lines that we do not care about
|
||||
if not line.startswith('|') or line.startswith('|---'):
|
||||
continue
|
||||
num_in_category += 1
|
||||
segments = line.split('|')[1:-1]
|
||||
if len(segments) < num_segments:
|
||||
add_error(line_num, "entry does not have all the required sections (have {}, need {})".format(
|
||||
len(segments), num_segments))
|
||||
continue
|
||||
# START Global
|
||||
for segment in segments:
|
||||
# every line segment should start and end with exactly 1 space
|
||||
if len(segment) - len(segment.lstrip()) != 1 or len(segment) - len(segment.rstrip()) != 1:
|
||||
add_error(line_num, "each segment must start and end with exactly 1 space")
|
||||
# END Global
|
||||
segments = [seg.strip() for seg in segments]
|
||||
check_entry(line_num, segments)
|
||||
# END Check Entries
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("No file passed (file should contain Markdown table syntax)")
|
||||
sys.exit(1)
|
||||
check_format(sys.argv[1])
|
||||
if len(errors) > 0:
|
||||
for err in errors:
|
||||
print(err)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,100 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import httplib2
|
||||
import re
|
||||
import socket
|
||||
import sys
|
||||
|
||||
|
||||
def parse_links(filename):
|
||||
"""Returns a list of URLs from text file"""
|
||||
with open(filename, mode='r', encoding='utf-8') as fp:
|
||||
readme = fp.read()
|
||||
index_section = readme.find('## Index')
|
||||
content = readme[index_section:]
|
||||
|
||||
raw_links = re.findall(
|
||||
'((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'\".,<>?«»“”‘’]))',
|
||||
content)
|
||||
|
||||
links = [
|
||||
str(raw_link[0]).rstrip('/') for raw_link in raw_links
|
||||
]
|
||||
|
||||
return links
|
||||
|
||||
def dup_links(links):
|
||||
"""Check for duplicated links"""
|
||||
print(f'Checking for duplicated links...')
|
||||
hasError = False
|
||||
seen = {}
|
||||
dupes = []
|
||||
|
||||
for link in links:
|
||||
if link not in seen:
|
||||
seen[link] = 1
|
||||
else:
|
||||
if seen[link] == 1:
|
||||
dupes.append(link)
|
||||
|
||||
if not dupes:
|
||||
print(f"No duplicate links")
|
||||
else:
|
||||
print(f"Found duplicate links: {dupes}")
|
||||
hasError = True
|
||||
return hasError
|
||||
|
||||
def validate_links(links):
|
||||
"""Checks each entry in JSON file for live link"""
|
||||
print(f'Validating {len(links)} links...')
|
||||
hasError = False
|
||||
for link in links:
|
||||
h = httplib2.Http(disable_ssl_certificate_validation=True, timeout=25)
|
||||
try:
|
||||
# fetching host name, removing leading www
|
||||
host = link.split('//', 1)[1].split('/', 1)[0]
|
||||
if host[:3] == 'www':
|
||||
host = host[4:]
|
||||
|
||||
resp = h.request(link + "/", headers={
|
||||
# Faking user agent as some hosting services block not-whitelisted UA
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1467.0 Safari/537.36',
|
||||
# setting host because Cloudflare returns 403 asking for captcha if host is missing
|
||||
'host': host
|
||||
})
|
||||
code = int(resp[0]['status'])
|
||||
# Checking status code errors
|
||||
if (code >= 400):
|
||||
hasError = True
|
||||
print(f"ERR:CLT:{code} : {link}")
|
||||
except TimeoutError:
|
||||
hasError = True
|
||||
print(f"ERR:TMO: {link}")
|
||||
except socket.error as socketerror:
|
||||
hasError = True
|
||||
print(f"ERR:SOC: {socketerror} : {link}")
|
||||
except Exception as e:
|
||||
hasError = True
|
||||
# Ignore some exceptions which are not actually errors.
|
||||
# The list below should be extended with other exceptions in the future if needed
|
||||
if (-1 != str(e).find("[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)")):
|
||||
print(f"ERR:SSL: {e} : {link}")
|
||||
elif (-1 != str(e).find("Content purported to be compressed with gzip but failed to decompress.")):
|
||||
print(f"ERR:GZP: {e} : {link}")
|
||||
elif (-1 != str(e).find("Unable to find the server at")):
|
||||
print(f"ERR:SRV: {e} : {link}")
|
||||
else:
|
||||
print(f"ERR:UKN: {e} : {link}")
|
||||
return hasError
|
||||
|
||||
if __name__ == "__main__":
|
||||
num_args = len(sys.argv)
|
||||
if num_args < 2:
|
||||
print("No .md file passed")
|
||||
sys.exit(1)
|
||||
links = parse_links(sys.argv[1])
|
||||
hasError = dup_links(links)
|
||||
if not hasError:
|
||||
hasError = validate_links(links)
|
||||
if hasError:
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user