578 lines
23 KiB
Python
578 lines
23 KiB
Python
from flask import Flask, render_template, send_from_directory, make_response, request, redirect, session, g, json, send_file, abort
|
|
import os
|
|
import random
|
|
import socket
|
|
import oracledb
|
|
import traceback
|
|
import requests
|
|
from logging.config import dictConfig
|
|
import secrets
|
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
|
import io
|
|
import json
|
|
from expiring_dict import ExpiringDict
|
|
|
|
|
|
|
|
|
|
|
|
capcha_site = '6LcJpHMgAAAAAMQLNY_g8J2Kv_qmCGureRN_lbGl'
|
|
capcha_site_sec = '6LcJpHMgAAAAAIUf4Jg_7NvawQKZoLoVypDU6-d8'
|
|
capcha_site_url='https://www.google.com/recaptcha/api/siteverify'
|
|
site = 'salvagedb.com'
|
|
app_path = os.path.dirname(os.path.realpath(__file__))
|
|
|
|
app = Flask(__name__)
|
|
|
|
app_debug : bool = os.environ.get('APP_DEBUG',False)
|
|
app.debug = os.environ.get('APP_DEBUG',False)
|
|
app.secret_key = secrets.token_hex()
|
|
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1)
|
|
|
|
os.environ['NLS_LANG'] = 'American_America.AL32UTF8'
|
|
|
|
#Cache
|
|
app.cache = ExpiringDict(60*60*24)
|
|
|
|
|
|
try:
|
|
gips = open('gips.txt').read().split('\n')
|
|
except:
|
|
gips=[]
|
|
|
|
if app_debug:
|
|
print(gips)
|
|
|
|
def save_request(request):
|
|
req_data = {}
|
|
req_data['endpoint'] = request.endpoint
|
|
req_data['method'] = request.method
|
|
req_data['cookies'] = request.cookies
|
|
req_data['data'] = request.data
|
|
req_data['headers'] = dict(request.headers)
|
|
req_data['headers'].pop('Cookie', None)
|
|
req_data['args'] = request.args
|
|
req_data['form'] = request.form
|
|
req_data['remote_addr'] = request.remote_addr
|
|
return req_data
|
|
|
|
|
|
dictConfig(
|
|
{
|
|
"version": 1,
|
|
"formatters": {
|
|
"default": {
|
|
"format": "[%(asctime)s] [%(levelname)s | %(module)s] %(message)s",
|
|
"datefmt": " %d/%m/%Y %H:%M:%S"
|
|
},
|
|
},
|
|
"handlers": {
|
|
"console": {
|
|
"class": "logging.StreamHandler",
|
|
"formatter": "default",
|
|
},
|
|
"file": {
|
|
"class": "logging.handlers.TimedRotatingFileHandler",
|
|
"filename": app_path + "/logs/app.log",
|
|
"when": "D",
|
|
"interval": 10,
|
|
"backupCount": 5,
|
|
"formatter": "default",
|
|
},
|
|
|
|
},
|
|
"root": {"level": "DEBUG", "handlers": ["console", "file"]},
|
|
}
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.after_request
|
|
def after_request(response):
|
|
if request.cookies.get('user_id', None) == None:
|
|
response.set_cookie('user_id', str(random.randint(0, 10000000000)), max_age=60 * 60 * 24 * 365 * 10)
|
|
return response
|
|
|
|
|
|
def init_session(connection, requestedTag_ignored):
|
|
pass
|
|
# cursor = connection.cursor()
|
|
# cursor.execute("""
|
|
# ALTER SESSION SET
|
|
# TIME_ZONE = 'UTC'
|
|
# NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI'""")
|
|
|
|
def start_pool():
|
|
pool_min = 4
|
|
pool_max = 4
|
|
pool_inc = 0
|
|
|
|
if app_debug:
|
|
print('Connecting to {}:{}/{}'.format(os.environ.get("DB_HOST"), os.environ.get("DB_PORT"), os.environ.get("DB_DBNAME")))
|
|
|
|
pool = oracledb.create_pool(
|
|
user=os.environ.get("DB_USERNAME"),
|
|
password=os.environ.get("DB_PASSWORD"),
|
|
dsn='{}:{}/{}'.format(os.environ.get("DB_HOST"), os.environ.get("DB_PORT"), os.environ.get("DB_DBNAME")),
|
|
#params=sample_env.get_pool_params(),
|
|
min=pool_min,
|
|
max=pool_max,
|
|
increment=pool_inc,
|
|
session_callback=init_session,
|
|
)
|
|
|
|
return pool
|
|
|
|
@app.route("/sitemap.xml")
|
|
def sitemap():
|
|
conn = pool.acquire()
|
|
cur = conn.cursor()
|
|
cur.execute('select distinct trunc(pg/40000)+1 nm from mv_pages');
|
|
nm = cur.fetchall()
|
|
return render_template('sitemap.xml', site=site, siten=nm)
|
|
|
|
@app.route("/sitemaps/<int:sitemap_id>.xml")
|
|
def sitemaps_xml(sitemap_id):
|
|
try:
|
|
id: int = int(sitemap_id)
|
|
conn = pool.acquire()
|
|
cur = conn.cursor()
|
|
cur.execute('select pg from mv_pages where sitemap_number = :p1', {'p1': id})
|
|
sitemap_pages = cur.fetchall()
|
|
return render_template('sitemaps.xml', site=site, sitemap_pages=sitemap_pages)
|
|
except:
|
|
app.logger.error(traceback.format_exc())
|
|
return 'bad request!', 500
|
|
|
|
@app.route("/")
|
|
def index_html():
|
|
try:
|
|
if 'maxnum' in app.cache:
|
|
if app_debug:
|
|
print('Find in cache max_num={}'.format(app.cache['maxnum']))
|
|
cnt = app.cache['maxnum']
|
|
else:
|
|
conn = pool.acquire()
|
|
cur = conn.cursor()
|
|
cur.execute('select max(num) from salvagedb')
|
|
cnt = "{:,}".format(cur.fetchone()[0])
|
|
app.cache['maxnum'] = cnt
|
|
return render_template('index.html', site=site, cnt=cnt ,capcha_site=capcha_site)
|
|
except:
|
|
app.logger.error(traceback.format_exc())
|
|
return 'bad request!', 500
|
|
|
|
@app.route("/privacy.html")
|
|
def privacy_html():
|
|
try:
|
|
|
|
return render_template('privacy.html', site=site)
|
|
except:
|
|
app.logger.error(traceback.format_exc())
|
|
return 'bad request!', 500
|
|
|
|
@app.route("/robots.txt")
|
|
def robot_txt():
|
|
try:
|
|
return render_template('robots.txt', site=site)
|
|
except:
|
|
app.logger.error(traceback.format_exc())
|
|
return 'bad request!', 500
|
|
|
|
@app.route("/decode", methods = ['POST'])
|
|
def decode():
|
|
try:
|
|
vin = request.form.get('q').strip()
|
|
g_respone = request.form['g-recaptcha-response']
|
|
capcha_check = requests.post(url=f'{capcha_site_url}?secret={capcha_site_sec}&response={g_respone}').json()
|
|
if capcha_check['success'] == False or capcha_check['score'] <0.5:
|
|
app.logger.info(f'Google reuest: {capcha_site_url}?secret={capcha_site_sec}&response={g_respone}')
|
|
app.logger.info(f'Bad google answer: {capcha_check}')
|
|
abort(401)
|
|
return redirect(f'/detail/{vin}.html', 301)
|
|
except:
|
|
app.logger.error(traceback.format_exc())
|
|
return 'bad request!', 500
|
|
|
|
|
|
@app.route("/decodevin.html")
|
|
def decodevin_html():
|
|
try:
|
|
return render_template('decodevin.html', site=site,capcha_site=capcha_site)
|
|
except:
|
|
app.logger.error(traceback.format_exc())
|
|
return 'bad request!', 500
|
|
|
|
@app.route("/database/page<int:page_num>.html")
|
|
def database_page_prc(page_num):
|
|
try:
|
|
pg = int(page_num)
|
|
conn = pool.acquire()
|
|
cur = conn.cursor()
|
|
user_ip = get_ip(request) ## определение ip клиента
|
|
try:
|
|
returnVal = cur.callfunc("checkip", int, [user_ip, request.headers.get("CF-IPCountry", 'None'), get_addr(user_ip), 1, 0, 0])
|
|
except:
|
|
print(request)
|
|
app.logger.error(traceback.format_exc())
|
|
|
|
cur.execute('select max(pg) from mv_pages')
|
|
max_page = int(cur.fetchall()[0][0])
|
|
cur.execute("""select rownum,s.vin,
|
|
COALESCE ((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='26'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Make'),'UNKNOWN') make,
|
|
COALESCE ((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='28'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Model'),'UNKNOWN') model,
|
|
COALESCE ((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='29'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Model Year'),'UNKNOWN') year
|
|
from salvagedb s
|
|
where num between (select mi from mv_pages where pg = :p1) and (select ma from mv_pages where pg = :p1)""",
|
|
{'p1': pg})
|
|
pgf = cur.fetchall()
|
|
return render_template('database.html', site=site, cur_page=pg, max_page=max_page, pg=pgf)
|
|
except:
|
|
app.logger.error(traceback.format_exc())
|
|
return 'bad request!', 500
|
|
|
|
@app.route("/detail/<vin>.html")
|
|
def detail_vin(vin):
|
|
try:
|
|
conn = pool.acquire()
|
|
cur = conn.cursor()
|
|
user_ip = get_ip(request) ## определение ip клиента
|
|
try:
|
|
returnVal = cur.callfunc("checkip", int, [user_ip, request.headers.get("CF-IPCountry", 'None'), get_addr(user_ip), 0, 0, 1])
|
|
except:
|
|
print(request)
|
|
app.logger.error(traceback.format_exc())
|
|
|
|
cur.execute("""select 'None', COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='26'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Make'),'UNKNOWN') make,
|
|
COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='28'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Model'),'UNKNOWN') model,
|
|
COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='29'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Model Year'),'UNKNOWN') year,
|
|
COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='5'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Body Class'),'UNKNOWN') body,
|
|
COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='13'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Engine Model'),'UNKNOWN') engine,
|
|
COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='9'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Engine Number of Cylinders'),'UNKNOWN') celindr,
|
|
COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='15'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Drive Type'),'-') drive
|
|
from (select substr(:p1,1,10) svin, :p1 vin from dual) s """, {'p1': vin})
|
|
res = cur.fetchall()
|
|
return render_template('details.html', site=site, vin=vin, det=res, capcha_site=capcha_site)
|
|
except:
|
|
app.logger.error(traceback.format_exc())
|
|
return 'bad request!', 500
|
|
|
|
|
|
@app.route('/search', methods = ['POST'])
|
|
def search():
|
|
try:
|
|
user_ip = get_ip(request) ## определение ip клиента
|
|
vin = request.form.get('q')
|
|
ua = request.headers.get('User-Agent')
|
|
app.logger.info(f'AgeNt: {ua}')
|
|
|
|
gmedia = False
|
|
if ua == 'Mediapartners-Google':
|
|
app.logger.info(f'Find MediaPartner Aget {ua}')
|
|
if user_ip in gips:
|
|
gmedia = True
|
|
else:
|
|
gmedia = False
|
|
try:
|
|
f = open('ips.txt','a')
|
|
f.write(f'{user_ip}\n')
|
|
finally:
|
|
f.close()
|
|
|
|
g_respone = request.args.get('g-recaptcha-response')
|
|
capcha_check = requests.post(url=f'{capcha_site_url}?secret={capcha_site_sec}&response={g_respone}').json()
|
|
if capcha_check['success'] == False or capcha_check['score'] <0.5:
|
|
app.logger.info(f'Google reuest: {capcha_site_url}?secret={capcha_site_sec}&response={g_respone}')
|
|
app.logger.info(f'Bad google answer: {capcha_check}')
|
|
if gmedia ==False and app_debug==True:
|
|
req_data = save_request(request)
|
|
app.logger.info(json.dumps(req_data, indent=4, default=str))
|
|
return 'bad req', 401
|
|
|
|
if len(vin) != 17:
|
|
return 'bad vin!', 500
|
|
conn = pool.acquire()
|
|
cur = conn.cursor()
|
|
returnVal = cur.callfunc("checkip", int, [user_ip, request.headers.get("CF-IPCountry", 'None'), get_addr(user_ip), 0, 1, 0])
|
|
|
|
cur.execute("""select 'None', COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='26'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Make'),'UNKNOWN') make,
|
|
COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='28'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Model'),'UNKNOWN') model,
|
|
COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='29'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Model Year'),'UNKNOWN') year,
|
|
COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='5'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Body Class'),'UNKNOWN') body,
|
|
COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='13'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Engine Model'),'UNKNOWN') engine,
|
|
COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='9'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Engine Number of Cylinders'),'UNKNOWN') celindr,
|
|
COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='15'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Drive Type'),'-') drive
|
|
from (select substr(:p1,1,10) svin, :p1 vin from dual) s """, {'p1': vin})
|
|
res = cur.fetchall()
|
|
cur.execute("""select rownum, t.vin, t.title, t.odo, t.odos, t.dem1, t.dem2, t.year||'/'||t.month from salvagedb t where vin = :p1 and svin = substr(:p1,1,10) """, {'p1': vin})
|
|
his = cur.fetchall()
|
|
return render_template('search.html', site=site, vin=vin, det=res, his=his)
|
|
except:
|
|
app.logger.error(traceback.format_exc())
|
|
return 'bad request!', 500
|
|
|
|
## API
|
|
@app.route("/api/search")
|
|
def api_search():
|
|
try:
|
|
access_code = request.args.get('access_code', None)
|
|
vin = request.args.get('vin', None)
|
|
|
|
user_ip = get_ip(request) ## определение ip клиента
|
|
|
|
# базовые проверки входящих аргументов
|
|
if len(vin) != 17 or vin is None:
|
|
ret = {'status': 'incorrect vin'}
|
|
response = app.response_class(
|
|
response=json.dumps(ret),
|
|
status=200,
|
|
mimetype='application/json'
|
|
)
|
|
if app.debug:
|
|
app.logger.debug(json.dumps(ret))
|
|
return response
|
|
if len(access_code) > 16 or access_code is None:
|
|
ret = {'status': 'incorrect access_code'}
|
|
response = app.response_class(
|
|
response=json.dumps(ret),
|
|
status=200,
|
|
mimetype='application/json'
|
|
)
|
|
if app.debug:
|
|
app.logger.debug(json.dumps(ret))
|
|
return response
|
|
|
|
conn = pool.acquire()
|
|
cur = conn.cursor()
|
|
|
|
## проверяем access_code
|
|
cur.execute(
|
|
'select t.summ, t.found_price, t.notfound_price, t.decode_price from restfact t where access_code = :p1',
|
|
{'p1': str(access_code)})
|
|
res = cur.fetchone()
|
|
summ = res[0]
|
|
found_price = res[1]
|
|
notfound_price = res[2]
|
|
decode_price = res[3]
|
|
|
|
### не достаточно средств
|
|
if summ <= 0:
|
|
ret = {'status': 'You have insufficient balance.'}
|
|
response = app.response_class(
|
|
response=json.dumps(ret),
|
|
status=200,
|
|
mimetype='application/json'
|
|
)
|
|
if app.debug:
|
|
app.logger.debug(json.dumps(ret))
|
|
return response
|
|
## ищем в истории
|
|
cur.execute('select t.odo,t.odos,t.title,t.dem1,t.dem2,t.year,t.month from salvagedb t where vin =:p1 and svin = :p2',
|
|
{'p1': vin.upper(), 'p2': vin.upper()[:10]})
|
|
res = cur.fetchall()
|
|
|
|
if len(res) > 0:
|
|
# found
|
|
dat = []
|
|
for it in res:
|
|
dat.append({
|
|
'odometer': it[0],
|
|
'odometer_status': it[1],
|
|
'title': it[2],
|
|
'damage1': it[3],
|
|
'damage2': it[4],
|
|
'add_to_db': '{}-{}'.format(it[5], it[6])
|
|
})
|
|
ret = {
|
|
'status': 'found',
|
|
'vin': vin.upper(),
|
|
'cost': found_price,
|
|
'records': dat
|
|
}
|
|
response = app.response_class(
|
|
response=json.dumps(ret),
|
|
status=200,
|
|
mimetype='application/json'
|
|
)
|
|
if app.debug:
|
|
app.logger.debug(json.dumps(ret))
|
|
cur.execute("insert into billing(access_code, vin, ip, status, dt, cost) values (:p1, :p2, :p3, :p4, CAST(SYSTIMESTAMP AT TIME ZONE 'UTC' AS DATE), :p5)",
|
|
{'p1': str(access_code), 'p2': str(vin), 'p3': str(user_ip), 'p4': 'FOUND', 'p5': found_price})
|
|
conn.commit()
|
|
return response
|
|
|
|
else:
|
|
# nor found
|
|
ret = {'status': 'NOT FOUND', 'cost': notfound_price}
|
|
if app.debug:
|
|
app.logger.debug(json.dumps(ret))
|
|
response = app.response_class(
|
|
response=json.dumps(ret),
|
|
status=200,
|
|
mimetype='application/json'
|
|
)
|
|
cur.execute("insert into billing(access_code, vin, ip, status, dt, cost) values (:p1, :p2, :p3, :p4, CAST(SYSTIMESTAMP AT TIME ZONE 'UTC' AS DATE), :p5)",
|
|
{'p1': str(access_code), 'p2': str(vin), 'p3': str(user_ip), 'p4': 'NOT FOUND', 'p5': notfound_price})
|
|
conn.commit()
|
|
return response
|
|
|
|
except:
|
|
app.logger.error(traceback.format_exc())
|
|
return 'bad request!', 500
|
|
|
|
@app.route("/api/restfact")
|
|
def api_restfact():
|
|
access_code = request.args.get('access_code', None)
|
|
if len(access_code) > 16 or access_code is None:
|
|
ret = {'status': 'incorrect access_code'}
|
|
response = app.response_class(
|
|
response=json.dumps(ret),
|
|
status=200,
|
|
mimetype='application/json'
|
|
)
|
|
if app.debug:
|
|
app.logger.debug(json.dumps(ret))
|
|
return response
|
|
|
|
conn = pool.acquire()
|
|
cur = conn.cursor()
|
|
cur.callproc('make_billing')
|
|
cur.execute(
|
|
'select t.summ, t.found_price, t.notfound_price, t.decode_price from restfact t where access_code = :p1',
|
|
{'p1': str(access_code)})
|
|
res = cur.fetchone()
|
|
summ = res[0]
|
|
if len(res) <= 0:
|
|
ret = {'status': 'incorrect access_code'}
|
|
response = app.response_class(
|
|
response=json.dumps(ret),
|
|
status=200,
|
|
mimetype='application/json'
|
|
)
|
|
if app.debug:
|
|
app.logger.debug(json.dumps(ret))
|
|
return response
|
|
else:
|
|
ret = {
|
|
'access_code': access_code,
|
|
'restfact': summ
|
|
}
|
|
response = app.response_class(
|
|
response=json.dumps(ret),
|
|
status=200,
|
|
mimetype='application/json'
|
|
)
|
|
if app.debug:
|
|
app.logger.debug(json.dumps(ret))
|
|
return response
|
|
|
|
@app.route("/api/restfact_detail")
|
|
def restfact_detail():
|
|
access_code = request.args.get('access_code', None)
|
|
if len(access_code) > 16 or access_code is None:
|
|
ret = {'status': 'incorrect access_code'}
|
|
response = app.response_class(
|
|
response=json.dumps(ret),
|
|
status=200,
|
|
mimetype='application/json'
|
|
)
|
|
if app.debug:
|
|
app.logger.debug(json.dumps(ret))
|
|
return response
|
|
|
|
conn = pool.acquire()
|
|
cur = conn.cursor()
|
|
cur.callproc('make_billing')
|
|
cur.execute('select rownum from restfact t where access_code = :p1', {'p1': str(access_code)})
|
|
res = cur.fetchall()
|
|
if len(res) <= 0:
|
|
ret = {'status': 'incorrect access_code'}
|
|
response = app.response_class(
|
|
response=json.dumps(ret),
|
|
status=200,
|
|
mimetype='application/json'
|
|
)
|
|
if app.debug:
|
|
app.logger.debug(json.dumps(ret))
|
|
return response
|
|
cur.execute("select vin, ip, status, dt, cost from billing where access_code = :p1 and dt > CAST(SYSTIMESTAMP AT TIME ZONE 'UTC' AS DATE) - 45 and made = 1 order by id", {'p1': str(access_code)})
|
|
res = cur.fetchall()
|
|
if len(res) <= 0:
|
|
ret = {'status': 'billing not found'}
|
|
response = app.response_class(
|
|
response=json.dumps(ret),
|
|
status=200,
|
|
mimetype='application/json'
|
|
)
|
|
if app.debug:
|
|
app.logger.debug(json.dumps(ret))
|
|
return response
|
|
else:
|
|
dat = []
|
|
for it in res:
|
|
dat.append(
|
|
{
|
|
'VIN': it[0],
|
|
'IP': it[1],
|
|
'STATUS': it[2],
|
|
'DATETIME': it[3].isoformat(),
|
|
'COST': it[4]
|
|
}
|
|
)
|
|
ret = {
|
|
'access_code': access_code,
|
|
'report': dat
|
|
}
|
|
response = app.response_class(
|
|
response=json.dumps(ret),
|
|
status=200,
|
|
mimetype='application/json'
|
|
)
|
|
if app.debug:
|
|
app.logger.debug(json.dumps(ret))
|
|
return response
|
|
|
|
@app.route("/ads.txt")
|
|
def ads_txt():
|
|
try:
|
|
return render_template('ads.txt')
|
|
except:
|
|
app.logger.error(traceback.format_exc())
|
|
return 'bad request!', 500
|
|
|
|
@app.route('/favicon.ico')
|
|
def logo():
|
|
"""Serves the logo image."""
|
|
|
|
with open(app_path+"/static/favicon.ico", 'rb') as bites:
|
|
return send_file(
|
|
io.BytesIO(bites.read()),
|
|
attachment_filename='favicon.ico',
|
|
mimetype='image/x-icon'
|
|
)
|
|
|
|
def get_ip(req) -> str:
|
|
if 'X-Forwarded-For' in req.headers:
|
|
proxy_data = req.headers['X-Forwarded-For']
|
|
ip_list = proxy_data.split(',')
|
|
user_ip = req.headers.get("Cf-Connecting-Ip") or ip_list[0] # first address in list is User IP
|
|
else:
|
|
user_ip = req.headers.get("Cf-Connecting-Ip") or req.remote_addr
|
|
return user_ip
|
|
|
|
def get_addr(req) -> str:
|
|
try:
|
|
return socket.gethostbyaddr(req)[0]
|
|
except:
|
|
return req
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# Start a pool of connections
|
|
pool = start_pool()
|
|
app.run(port=int(os.environ.get('PORT', '8080')))
|
|
|