Adding API server files
This commit is contained in:
parent
937a12cc50
commit
1e2e688453
12
src/api/.gitignore
vendored
Normal file
12
src/api/.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.vscode/
|
||||||
|
__pycache__/
|
||||||
|
*.swp
|
||||||
|
config.py
|
||||||
|
.idea/
|
||||||
|
py3.7/
|
||||||
|
py3/
|
||||||
|
py3.8/
|
||||||
|
*.db
|
||||||
|
*.code-workspace
|
||||||
|
*.log
|
||||||
|
py*/
|
||||||
1068
src/api/README.md
Normal file
1068
src/api/README.md
Normal file
File diff suppressed because it is too large
Load Diff
8
src/api/config-example.py
Normal file
8
src/api/config-example.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
dbfolder = ''
|
||||||
|
debug_status = False
|
||||||
|
sse_pubKey = '<public key in the format of pybtc python library>'
|
||||||
|
apiUrl = 'https://flosight.duckdns.org/api/'
|
||||||
|
|
||||||
|
# your apilayer.net access key
|
||||||
|
apilayerAccesskey = '<accesskey>'
|
||||||
|
|
||||||
150
src/api/fetchRates.py
Normal file
150
src/api/fetchRates.py
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import sqlite3
|
||||||
|
import os
|
||||||
|
from config import *
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import sqlite3
|
||||||
|
import os
|
||||||
|
from config import *
|
||||||
|
import time
|
||||||
|
|
||||||
|
RETRY_TIMEOUT_DB = 60 # 60 sec
|
||||||
|
RETRY_TIMEOUT_REQUEST = 10 * 60 # 10 minsd
|
||||||
|
|
||||||
|
prices = {}
|
||||||
|
# 1. fetch old price data if its there, else create an empty db
|
||||||
|
def connect_database():
|
||||||
|
if not os.path.isfile(f"system.db"):
|
||||||
|
# create an empty db
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
conn = sqlite3.connect('system.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute('''CREATE TABLE ratepairs
|
||||||
|
(id integer primary key, ratepair text, price real)''')
|
||||||
|
c.execute("INSERT INTO ratepairs(ratepair, price) VALUES ('BTCBTC', 1)")
|
||||||
|
c.execute("INSERT INTO ratepairs(ratepair, price) VALUES ('BTCUSD', -1)")
|
||||||
|
c.execute("INSERT INTO ratepairs(ratepair, price) VALUES ('BTCINR', -1)")
|
||||||
|
c.execute("INSERT INTO ratepairs(ratepair, price) VALUES ('USDINR', -1)")
|
||||||
|
c.execute("INSERT INTO ratepairs(ratepair, price) VALUES ('FLOUSD', -1)")
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
except:
|
||||||
|
print(f"Unable to create system.db, retrying in {RETRY_TIMEOUT_DB} sec")
|
||||||
|
time.sleep(RETRY_TIMEOUT_DB)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
# load old price data
|
||||||
|
# load older price data
|
||||||
|
global prices
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
conn = sqlite3.connect('system.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
ratepairs = c.execute('select ratepair, price from ratepairs')
|
||||||
|
ratepairs = ratepairs.fetchall()
|
||||||
|
for ratepair in ratepairs:
|
||||||
|
ratepair = list(ratepair)
|
||||||
|
prices[ratepair[0]] = ratepair[1]
|
||||||
|
except:
|
||||||
|
print(f"Unable to read system.db, retrying in {RETRY_TIMEOUT_DB} sec")
|
||||||
|
time.sleep(RETRY_TIMEOUT_DB)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
# 2. fetch new price data
|
||||||
|
def fetch_newprice():
|
||||||
|
global prices
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
# apilayer
|
||||||
|
response = requests.get(f"http://apilayer.net/api/live?access_key={apilayerAccesskey}")
|
||||||
|
try:
|
||||||
|
price = response.json()
|
||||||
|
prices['USDINR'] = price['quotes']['USDINR']
|
||||||
|
break
|
||||||
|
except ValueError:
|
||||||
|
print('Json parse error. retrying in {RETRY_TIMEOUT_REQUEST} sec')
|
||||||
|
time.sleep(RETRY_TIMEOUT_REQUEST)
|
||||||
|
except:
|
||||||
|
print(f"Unable to fetch new price data, retrying in {RETRY_TIMEOUT_REQUEST} sec")
|
||||||
|
time.sleep(RETRY_TIMEOUT_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_bitpay_or_coindesk():
|
||||||
|
# bitpay
|
||||||
|
global prices
|
||||||
|
while True:
|
||||||
|
print("Trying bitpay API")
|
||||||
|
try:
|
||||||
|
response = requests.get('https://bitpay.com/api/rates')
|
||||||
|
bitcoinRates = response.json()
|
||||||
|
for currency in bitcoinRates:
|
||||||
|
if currency['code'] == 'USD':
|
||||||
|
prices['BTCUSD'] = currency['rate']
|
||||||
|
elif currency['code'] == 'INR':
|
||||||
|
prices['BTCINR'] = currency['rate']
|
||||||
|
except ValueError:
|
||||||
|
print("Json parse error in bitpay")
|
||||||
|
except:
|
||||||
|
print(f"Unable to fetch bitpay")
|
||||||
|
else:
|
||||||
|
break # if data is accrued from bitpay, break from loop and procees to next process
|
||||||
|
print("Trying coindesk API")
|
||||||
|
# coindesk
|
||||||
|
try:
|
||||||
|
response = requests.get('https://api.coindesk.com/v1/bpi/currentprice.json')
|
||||||
|
price = response.json()
|
||||||
|
prices['BTCUSD'] = price['bpi']['USD']['rate']
|
||||||
|
except ValueError:
|
||||||
|
print(f'Json parse error in coindesk')
|
||||||
|
except:
|
||||||
|
print(f"Unable to fetch coindesk")
|
||||||
|
else:
|
||||||
|
break # if data is accrued from coindesk, break from loop and procees to next process
|
||||||
|
|
||||||
|
print(f"Retrying in {RETRY_TIMEOUT_REQUEST} sec")
|
||||||
|
time.sleep(RETRY_TIMEOUT_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
# cryptocompare
|
||||||
|
def fetch_cryptocompare():
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
response = requests.get('https://min-api.cryptocompare.com/data/histoday?fsym=FLO&tsym=USD&limit=1&aggregate=3&e=CCCAGG')
|
||||||
|
price = response.json()
|
||||||
|
prices['FLOUSD'] = price['Data'][-1]['close']
|
||||||
|
except ValueError:
|
||||||
|
print(f'Json parse error in cryptocompare, retrying in {RETRY_TIMEOUT_REQUEST} sec')
|
||||||
|
except:
|
||||||
|
print(f"Unable to fetch cryptocompare, retrying in {RETRY_TIMEOUT_REQUEST} sec")
|
||||||
|
else:
|
||||||
|
break # if data is accrued from coindesk, break from loop and procees to next process
|
||||||
|
|
||||||
|
# 3. update latest price data
|
||||||
|
def update_latest_prices():
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
conn = sqlite3.connect('system.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
for pair in list(prices.items()):
|
||||||
|
pair = list(pair)
|
||||||
|
c.execute(f"UPDATE ratepairs SET price={pair[1]} WHERE ratepair='{pair[0]}'")
|
||||||
|
conn.commit()
|
||||||
|
except:
|
||||||
|
print(f"Unable to write to system.db, retrying in {RETRY_TIMEOUT_DB} sec")
|
||||||
|
time.sleep(RETRY_TIMEOUT_DB)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
connect_database()
|
||||||
|
fetch_newprice()
|
||||||
|
fetch_bitpay_or_coindesk()
|
||||||
|
fetch_cryptocompare()
|
||||||
|
print('\n\n')
|
||||||
|
print(prices)
|
||||||
|
update_latest_prices()
|
||||||
1240
src/api/parsing.py
Normal file
1240
src/api/parsing.py
Normal file
File diff suppressed because it is too large
Load Diff
2880
src/api/ranchimallflo_api.py
Normal file
2880
src/api/ranchimallflo_api.py
Normal file
File diff suppressed because it is too large
Load Diff
31
src/api/requirements.txt
Normal file
31
src/api/requirements.txt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
aiofiles
|
||||||
|
APScheduler==3.9.1
|
||||||
|
arrow==0.15.2
|
||||||
|
blinker==1.4
|
||||||
|
certifi==2019.9.11
|
||||||
|
cffi
|
||||||
|
chardet==3.0.4
|
||||||
|
Click==7.0
|
||||||
|
h11==0.9.0
|
||||||
|
h2==3.1.1
|
||||||
|
hpack==3.0.0
|
||||||
|
Hypercorn==0.8.2
|
||||||
|
hyperframe==5.2.0
|
||||||
|
idna==2.8
|
||||||
|
itsdangerous==1.1.0
|
||||||
|
Jinja2==2.10.1
|
||||||
|
MarkupSafe==1.1.1
|
||||||
|
multidict==4.5.2
|
||||||
|
priority==1.3.0
|
||||||
|
pyflo-lib==2.0.9
|
||||||
|
pycparser==2.19
|
||||||
|
python-dateutil==2.8.0
|
||||||
|
Quart==0.10.0
|
||||||
|
Quart-CORS==0.2.0
|
||||||
|
requests==2.22.0
|
||||||
|
six==1.12.0
|
||||||
|
sortedcontainers==2.1.0
|
||||||
|
toml==0.10.0
|
||||||
|
typing-extensions==3.7.4
|
||||||
|
urllib3==1.25.3
|
||||||
|
wsproto==0.15.0
|
||||||
24
src/api/static/broadcast.js
Normal file
24
src/api/static/broadcast.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var es = new EventSource('/sse');
|
||||||
|
es.onmessage = function (event) {
|
||||||
|
var messages_dom = document.getElementsByTagName('ul')[0];
|
||||||
|
var message_dom = document.createElement('li');
|
||||||
|
var content_dom = document.createTextNode('Received: ' + event.data);
|
||||||
|
message_dom.appendChild(content_dom);
|
||||||
|
messages_dom.appendChild(message_dom);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('send').onclick = function() {
|
||||||
|
fetch('/', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify ({
|
||||||
|
message: document.getElementsByName("message")[0].value,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
document.getElementsByName("message")[0].value = "";
|
||||||
|
};
|
||||||
|
});
|
||||||
12
src/api/templates/index.html
Normal file
12
src/api/templates/index.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>SSSE example</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<input name="message" type="text"></input>
|
||||||
|
<button id="send">Send</button>
|
||||||
|
<ul></ul>
|
||||||
|
<script type="text/javascript" src="{{ url_for('static', filename='broadcast.js') }}"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4
src/api/wsgi.py
Normal file
4
src/api/wsgi.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from ranchimallflo_api import app
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run()
|
||||||
Loading…
Reference in New Issue
Block a user