Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
import os, time, json, base64, requests
|
| 2 |
from bs4 import BeautifulSoup
|
| 3 |
from flask import Flask, request, jsonify, Response, stream_with_context
|
| 4 |
from flask_cors import CORS
|
|
@@ -23,44 +23,27 @@ def scrape_startpage(query, n=10):
|
|
| 23 |
results = []
|
| 24 |
for c in soup.find_all('div', class_='result')[:n]:
|
| 25 |
t = c.find('a', class_='result-title')
|
| 26 |
-
if not t:
|
| 27 |
-
continue
|
| 28 |
d = c.find('p', class_='result-description') or c.find('span', class_='result-description')
|
| 29 |
-
results.append({
|
| 30 |
-
'title': t.get_text(strip=True),
|
| 31 |
-
'url': t.get('href'),
|
| 32 |
-
'desc': d.get_text(strip=True) if d else ''
|
| 33 |
-
})
|
| 34 |
return results
|
| 35 |
except Exception:
|
| 36 |
return []
|
| 37 |
|
| 38 |
def get_weather_from_ip(ip_address):
|
| 39 |
try:
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
if ip_data.get('error'):
|
| 44 |
-
return {'error': 'Invalid IP'}
|
| 45 |
-
loc = ip_data.get('loc', '')
|
| 46 |
-
if not loc:
|
| 47 |
-
return {'error': 'No location'}
|
| 48 |
lat, lon = loc.split(',')
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
return {'error': 'US only'}
|
| 53 |
-
points = requests.get(f'https://api.weather.gov/points/{lat},{lon}').json()
|
| 54 |
-
forecast_url = points['properties']['forecast']
|
| 55 |
-
forecast = requests.get(forecast_url).json()
|
| 56 |
current = forecast['properties']['periods'][0]
|
| 57 |
return {
|
| 58 |
'ip': ip_address,
|
| 59 |
-
'location': {'city': city, 'country': country, 'latitude': lat, 'longitude': lon},
|
| 60 |
-
'weather': {
|
| 61 |
-
'temperature': current['temperature'], 'feels_like': None, 'humidity': None,
|
| 62 |
-
'description': current['detailedForecast'], 'icon': None
|
| 63 |
-
}
|
| 64 |
}
|
| 65 |
except Exception as e:
|
| 66 |
return {'error': str(e)}
|
|
@@ -68,19 +51,16 @@ def get_weather_from_ip(ip_address):
|
|
| 68 |
@app.route('/search')
|
| 69 |
def search():
|
| 70 |
q = request.args.get('q')
|
| 71 |
-
if not q:
|
| 72 |
-
return jsonify({'error': 'Missing q'}), 400
|
| 73 |
n = request.args.get('n', default=10, type=int)
|
| 74 |
return jsonify({'query': q, 'results': scrape_startpage(q, n)})
|
| 75 |
|
| 76 |
@app.route('/weather')
|
| 77 |
def weather():
|
| 78 |
ip = request.args.get('ip')
|
| 79 |
-
if not ip:
|
| 80 |
-
return jsonify({'error': 'Missing ip'}), 400
|
| 81 |
data = get_weather_from_ip(ip)
|
| 82 |
-
if 'error' in data:
|
| 83 |
-
return jsonify(data), 400
|
| 84 |
return jsonify(data)
|
| 85 |
|
| 86 |
@app.route('/')
|
|
@@ -88,19 +68,11 @@ def health():
|
|
| 88 |
return jsonify({'status': 'running', 'message': 'GridLock search API'})
|
| 89 |
|
| 90 |
def morsify_key():
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
seq = [b1[::-1], b2[::2] + b3[1::2], b4[::-1], b5]
|
| 97 |
-
j = "".join(seq)
|
| 98 |
-
z = base64.b64encode(j.encode()).decode()
|
| 99 |
-
y = "".join(chr((ord(c) - i) % 126) for i, c in enumerate(z))
|
| 100 |
-
x = base64.b64decode(base64.b64encode(y.encode())).decode()
|
| 101 |
-
mix = "".join(chr(ord(a) ^ ord(b)) for a, b in zip(x, itertools.cycle("K3yMix")))
|
| 102 |
-
clean = base64.b64decode(base64.b64encode(mix.encode())).decode()
|
| 103 |
-
return "".join(reversed(clean))[40:]+clean[:40]
|
| 104 |
|
| 105 |
@app.route('/v1/chat/completions', methods=['POST'])
|
| 106 |
def chat_completions():
|
|
@@ -125,8 +97,7 @@ def chat_completions():
|
|
| 125 |
if stream:
|
| 126 |
def generate():
|
| 127 |
for line in r.iter_lines():
|
| 128 |
-
if line:
|
| 129 |
-
yield f"data: {line.decode('utf-8')}\n\n"
|
| 130 |
return Response(stream_with_context(generate()), content_type='text/event-stream')
|
| 131 |
else:
|
| 132 |
return jsonify(r.json())
|
|
|
|
| 1 |
+
import os, time, json, base64, requests
|
| 2 |
from bs4 import BeautifulSoup
|
| 3 |
from flask import Flask, request, jsonify, Response, stream_with_context
|
| 4 |
from flask_cors import CORS
|
|
|
|
| 23 |
results = []
|
| 24 |
for c in soup.find_all('div', class_='result')[:n]:
|
| 25 |
t = c.find('a', class_='result-title')
|
| 26 |
+
if not t: continue
|
|
|
|
| 27 |
d = c.find('p', class_='result-description') or c.find('span', class_='result-description')
|
| 28 |
+
results.append({'title': t.get_text(strip=True), 'url': t.get('href'), 'desc': d.get_text(strip=True) if d else ''})
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
return results
|
| 30 |
except Exception:
|
| 31 |
return []
|
| 32 |
|
| 33 |
def get_weather_from_ip(ip_address):
|
| 34 |
try:
|
| 35 |
+
ip_data = requests.get(f'https://ipinfo.io/{ip_address}/json').json()
|
| 36 |
+
loc = ip_data.get('loc')
|
| 37 |
+
if not loc: return {'error': 'No location'}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
lat, lon = loc.split(',')
|
| 39 |
+
if ip_data.get('country') != 'US':
|
| 40 |
+
return {'error': 'Weather only available in US'}
|
| 41 |
+
forecast = requests.get(requests.get(f'https://api.weather.gov/points/{lat},{lon}').json()['properties']['forecast']).json()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
current = forecast['properties']['periods'][0]
|
| 43 |
return {
|
| 44 |
'ip': ip_address,
|
| 45 |
+
'location': {'city': ip_data.get('city', 'Unknown'), 'country': ip_data.get('country'), 'latitude': lat, 'longitude': lon},
|
| 46 |
+
'weather': {'temperature': current['temperature'], 'description': current['detailedForecast']}
|
|
|
|
|
|
|
|
|
|
| 47 |
}
|
| 48 |
except Exception as e:
|
| 49 |
return {'error': str(e)}
|
|
|
|
| 51 |
@app.route('/search')
|
| 52 |
def search():
|
| 53 |
q = request.args.get('q')
|
| 54 |
+
if not q: return jsonify({'error': 'Missing query'}), 400
|
|
|
|
| 55 |
n = request.args.get('n', default=10, type=int)
|
| 56 |
return jsonify({'query': q, 'results': scrape_startpage(q, n)})
|
| 57 |
|
| 58 |
@app.route('/weather')
|
| 59 |
def weather():
|
| 60 |
ip = request.args.get('ip')
|
| 61 |
+
if not ip: return jsonify({'error': 'Missing ip'}), 400
|
|
|
|
| 62 |
data = get_weather_from_ip(ip)
|
| 63 |
+
if 'error' in data: return jsonify(data), 400
|
|
|
|
| 64 |
return jsonify(data)
|
| 65 |
|
| 66 |
@app.route('/')
|
|
|
|
| 68 |
return jsonify({'status': 'running', 'message': 'GridLock search API'})
|
| 69 |
|
| 70 |
def morsify_key():
|
| 71 |
+
prefix = "nvapi-"
|
| 72 |
+
rest_enc = "zAPHnOBRkqd0ZogQ4h4lZh4c8lZ4LgOcOOlhLL"
|
| 73 |
+
shift = 8
|
| 74 |
+
decoded = ''.join(chr((ord(c)-shift) % 126) for c in rest_enc)
|
| 75 |
+
return prefix + decoded
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
@app.route('/v1/chat/completions', methods=['POST'])
|
| 78 |
def chat_completions():
|
|
|
|
| 97 |
if stream:
|
| 98 |
def generate():
|
| 99 |
for line in r.iter_lines():
|
| 100 |
+
if line: yield f"data: {line.decode()}\n\n"
|
|
|
|
| 101 |
return Response(stream_with_context(generate()), content_type='text/event-stream')
|
| 102 |
else:
|
| 103 |
return jsonify(r.json())
|