1
1
mirror of https://github.com/chubin/cheat.sh.git synced 2024-11-23 10:35:29 +03:00

queries logging, github buttons, ?T and ?q

This commit is contained in:
Igor Chubin 2017-05-26 09:17:39 +00:00
parent c4b197e71b
commit 0609f0fb23
3 changed files with 127 additions and 15 deletions

View File

@ -27,7 +27,7 @@ app = Flask(__name__)
MYDIR = os.path.abspath(os.path.dirname( os.path.dirname('__file__') ))
sys.path.append("%s/lib/" % MYDIR)
from globals import LOG_FILE, TEMPLATES, STATIC, log, error
from globals import FILE_QUERIES_LOG, LOG_FILE, TEMPLATES, STATIC, log, error
from cheat_wrapper import cheat_wrapper, save_cheatsheet
@ -47,6 +47,31 @@ def is_html_needed(user_agent):
return False
return True
def parse_args(args):
result = {}
q = ""
for key, val in args.items():
if len(val) == 0:
q += key
continue
if q is None:
return result
if 'T' in q:
result['no-terminal'] = True
if 'q' in q:
result['quiet'] = True
for key, val in args.items():
if val == 'True':
val = True
if val == 'False':
val = False
result[key] = val
return result
@app.route('/files/<path:path>')
def send_static(path):
return send_from_directory(STATIC, path)
@ -59,6 +84,11 @@ def send_favicon():
def send_malformed():
return send_from_directory(STATIC, 'malformed-response.html')
def log_query(ip, found, topic, user_agent):
log_entry = "%s %s %s %s" % (ip, found, topic, user_agent)
with open(FILE_QUERIES_LOG, 'a') as my_file:
my_file.write(log_entry+"\n")
@app.route("/", methods=['GET', 'POST'])
@app.route("/<path:topic>", methods=["GET", "POST"])
def answer(topic = None):
@ -76,6 +106,21 @@ def answer(topic = None):
user_agent = request.headers.get('User-Agent', '').lower()
html_needed = is_html_needed(user_agent)
options = parse_args(request.args)
if request.headers.getlist("X-Forwarded-For"):
ip = request.headers.getlist("X-Forwarded-For")[0]
if ip.startswith('::ffff:'):
ip = ip[7:]
else:
ip = request.remote_addr
if request.headers.getlist("X-Forwarded-For"):
ip = request.headers.getlist("X-Forwarded-For")[0]
if ip.startswith('::ffff:'):
ip = ip[7:]
else:
ip = request.remote_addr
if request.method == 'POST':
for k, v in request.form.items():
@ -109,8 +154,9 @@ def answer(topic = None):
if topic is None:
topic = ":firstpage"
answer = cheat_wrapper(topic, html=is_html_needed(user_agent))
answer, found = cheat_wrapper(topic, request_options=options, html=is_html_needed(user_agent))
log_query(ip, found, topic, user_agent)
return answer
server = WSGIServer(("", 8002), app) # log=None)

View File

@ -198,14 +198,26 @@ def split_paragraphs(text):
return answer
def paragraph_contains(paragraph, keyword, insensitive=False, word_boundaries=True):
regex = re.escape(keyword)
if not word_boundaries:
regex = r"\b%s\b" % keyword
"""
Several keywords can be joined together using ~
For example: ~ssh~passphrase
"""
answer = True
if insensitive:
answer = bool(re.search(regex, paragraph, re.IGNORECASE))
if '~' in keyword:
keywords = keyword.split('~')
else:
answer = bool(re.search(regex, paragraph))
keywords = [keyword]
for keyword in keywords:
regex = re.escape(keyword)
if not word_boundaries:
regex = r"\b%s\b" % keyword
if insensitive:
answer = answer and bool(re.search(regex, paragraph, re.IGNORECASE))
else:
answer = answer and bool(re.search(regex, paragraph))
return answer
@ -322,9 +334,39 @@ def colorize_internal(topic, answer, html_needed):
return answer
def github_button(topic_type):
repository = {
"cheat.sheets": 'chubin/cheat.sheets',
"cheat.sheets dir": 'chubin/cheat.sheets',
"tldr": 'tldr-pages/tldr',
"internal": '',
"cheat": 'chrisallenlane/cheat',
"search": '',
"internal": '',
"unknown": '',
}
full_name = repository.get(topic_type, '')
if not full_name:
return ''
short_name = full_name.split('/',1)[1]
button = (
"<!-- Place this tag where you want the button to render. -->"
'<a aria-label="Star %(full_name)s on GitHub" data-count-aria-label="# stargazers on GitHub"'
' data-count-api="/repos/%(full_name)s#stargazers_count"'
' data-count-href="/%(full_name)s/stargazers"'
' data-icon="octicon-star"'
' href="https://github.com/%(full_name)s"'
' class="github-button">%(short_name)s</a>'
) % locals()
return button
#
def cheat_wrapper(query, highlight=True, html=False):
def cheat_wrapper(query, request_options=None, html=False):
highlight = not bool(request_options and request_options.get('no-terminal'))
keyword = None
if '~' in query:
@ -346,6 +388,8 @@ def cheat_wrapper(query, highlight=True, html=False):
search_mode = False
found = True # if the page was found in the database
editable = False # can generated page be edited on github (only cheat.sheets pages can)
result = ""
for topic, answer in answers:
@ -357,6 +401,9 @@ def cheat_wrapper(query, highlight=True, html=False):
highlight = False
topic_type = get_topic_type(topic)
if topic_type == 'unknown':
found = False
if highlight:
if topic_type.endswith(" dir"):
pass
@ -376,19 +423,29 @@ def cheat_wrapper(query, highlight=True, html=False):
else:
answer = pygments_highlight(answer, BashLexer(), Terminal256Formatter(style='native'))
if topic_type == "cheat.sheets":
editable = True
if search_mode:
result += "\n%s%s %s %s%s\n" % (colored.bg('dark_gray'), colored.attr("res_underlined"), topic, colored.attr("res_underlined"), colored.attr('reset'))
if highlight:
result += "\n%s%s %s %s%s\n" % (colored.bg('dark_gray'), colored.attr("res_underlined"), topic, colored.attr("res_underlined"), colored.attr('reset'))
else:
result += "[%s]" % topic
result += answer
if search_mode:
result = result[1:]
editable = False
repository_button = ''
else:
repository_button = github_button(topic_type)
if html:
result = result + "\n$"
result = html_wrapper(result)
title = "<title>cheat.sh/%s</title>" % topic
title += '\n<link rel="stylesheet" href="/files/awesomplete.css" /><script src="/files/awesomplete.min.js" async></script>'
# title += '\n<link rel="stylesheet" href="/files/awesomplete.css" />script src="/files/awesomplete.min.js" async></script>'
# submit button: thanks to http://stackoverflow.com/questions/477691/
submit_button = '<input type="submit" style="position: absolute; left: -9999px; width: 1px; height: 1px;" tabindex="-1" />'
topic_list = """
@ -397,10 +454,18 @@ def cheat_wrapper(query, highlight=True, html=False):
""" % ("\n".join("<option value='%s'></option>" % x for x in get_topics_list()))
curl_line = "<span class='pre'>$ curl cheat.sh/</span>"
form_html = '<form action="/" method="GET"/>%s%s<input type="text" value="%s" name="topic" list="topics" class="awesomplete_" autofocus autocomplete="off"/>%s</form>' % (submit_button, curl_line, query, topic_list)
result = re.sub("<pre>", form_html + "<pre>", result)
if query == ':firstpage':
query = ""
form_html = '<form action="/" method="GET"/>%s%s<input type="text" value="%s" name="topic" list="topics" autofocus autocomplete="off"/>%s</form>' % (submit_button, curl_line, query, topic_list)
edit_button = ''
if editable:
edit_page_link = 'https://github.com/chubin/cheat.sheets/edit/master/sheets/' + topic
edit_button = '<pre style="position:absolute;padding-left:40em;overflow:visible;height:0;">[<a href="%s" style="color:cyan">edit</a>]</pre>' % edit_page_link
result = re.sub("<pre>", edit_button + form_html + "<pre>", result)
result = re.sub("<head>", "<head>" + title, result)
result = result.replace('</body>', TWITTER_BUTTON + GITHUB_BUTTON + GITHUB_BUTTON_2 + GITHUB_BUTTON_FOOTER + '</body>')
if not request_options.get('quiet'):
result = result.replace('</body>', TWITTER_BUTTON + GITHUB_BUTTON + repository_button + GITHUB_BUTTON_FOOTER + '</body>')
return result
return result, found

View File

@ -6,6 +6,7 @@ MYDIR = os.path.abspath(os.path.dirname( os.path.dirname('__file__') ))
ANSI2HTML = os.path.join( MYDIR, "share/ansi2html.sh" )
LOG_FILE = os.path.join( MYDIR, 'log/main.log' )
FILE_QUERIES_LOG = os.path.join( MYDIR, 'log/queries.log' )
TEMPLATES = os.path.join( MYDIR, 'share/templates' )
STATIC = os.path.join( MYDIR, 'share/static' )