Compare commits
63 Commits
e146811553
...
fintic-dev
Author | SHA1 | Date | |
---|---|---|---|
|
872e6a0172 | ||
|
db4fd6faa5 | ||
|
9e029407de | ||
|
b1add6ae8d | ||
|
8e28f6cd29 | ||
|
ee62f88110 | ||
|
dae16ab719 | ||
|
13d2377719 | ||
|
93a80866d2 | ||
|
58805d63c6 | ||
|
fb535bc82e | ||
|
e5ce5c4337 | ||
|
f59eca70f0 | ||
|
7409bbb286 | ||
|
34a5e789b5 | ||
|
d5c3f032c4 | ||
|
046775c2d3 | ||
|
934026d6ad | ||
|
12cf1fa1bc | ||
|
013ee0eb7e | ||
|
fd782c6fbe | ||
|
f435cbd9bb | ||
|
3083bf9458 | ||
|
c32e1ab105 | ||
|
78b121accd | ||
|
82ef4697e5 | ||
|
14087cd4bc | ||
|
df30ffd7b8 | ||
|
b2266ada26 | ||
|
f1c01d1877 | ||
|
39e0f95728 | ||
|
d10a9a65b6 | ||
|
b76a787d30 | ||
|
c6ca87adc7 | ||
|
5673bebad2 | ||
|
2005623025 | ||
|
b08fd37013 | ||
|
947d8df292 | ||
|
78058df0b4 | ||
|
35b2277996 | ||
|
8a5c2f3e3d | ||
|
6092e54414 | ||
|
9bee6a7416 | ||
|
2f51fd206e | ||
|
5ee369e6ba | ||
|
1b8c948aaa | ||
|
ca2cbce648 | ||
|
56c35d4bd1 | ||
|
3e32b4c45e | ||
|
f5787097e1 | ||
|
8a045e2513 | ||
|
aeae1a56d3 | ||
|
f331c70454 | ||
|
440c92a4c5 | ||
|
4ec8bbf680 | ||
|
795a045a7e | ||
|
9ee2f495ee | ||
|
4903062ad0 | ||
|
7f0b68f05a | ||
|
1c5477527b | ||
|
9e552cea74 | ||
|
195b93a250 | ||
|
14f2aad03d |
7
.gitignore
vendored
@@ -1,7 +0,0 @@
|
||||
*.json
|
||||
*.csv
|
||||
*.txt
|
||||
*.pyc
|
||||
__pycache__/*
|
||||
user_uploads/*
|
||||
display_images/*
|
@@ -1,29 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Update system and install required dependencies
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get upgrade -y
|
||||
|
||||
sudo apt-get install \
|
||||
python3-dev \
|
||||
python3-pip \
|
||||
python3-pillow \
|
||||
libatlas-base-dev \
|
||||
libopenjp2-7 \
|
||||
libtiff5
|
||||
|
||||
# Remove packages
|
||||
|
||||
sudo apt-get remove -y \
|
||||
bluez \
|
||||
bluez-firmware \
|
||||
pi-bluetooth \
|
||||
triggerhappy \
|
||||
pigpio
|
||||
|
||||
sudo apt-get autoremove -y
|
||||
|
||||
# Clear the cache
|
||||
|
||||
sudo apt-get clean -y
|
@@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
sudo -H pip3 install -u pip
|
||||
|
||||
cd rpi-rgb-led-matrix || exit 1
|
||||
|
||||
make build-python PYTHON="$(which python3)"
|
||||
sudo make install-python PYTHON="$(which python3)"
|
||||
|
||||
cd ..
|
||||
|
||||
sudo -H pip3 install -r requirements.txt
|
@@ -1,22 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Disable onboard audio
|
||||
sudo sed -i 's/dtparam=audio.*/dtparam=audio=off/g' /boot/config.txt
|
||||
|
||||
# Disable onboard bluetooth
|
||||
echo "dtoverlay=disable-bt" | sudo tee -a /boot/config.txt
|
||||
|
||||
# Increase default temperature limit from 60C to 70C
|
||||
echo "temp_soft_limit=70" | sudo tee -a /boot/config.txt
|
||||
|
||||
# Isolate (remove) CPU core 3 from kernel process scheduler
|
||||
#? Is this just to run a little cooler?
|
||||
sudo sed -i '$ s/$/ isolcpus=3/' /boot/cmdline.txt
|
||||
|
||||
# Enable ssh server on boot
|
||||
sudo touch /boot/ssh.txt
|
||||
|
||||
# Disable hdmi output
|
||||
sudo sed -i 's/exit 0//g' /etc/rc.local
|
||||
echo "/usr/bin/tvservice -o" | sudo tee -a /etc/rc.local
|
||||
echo "exit 0" | sudo tee -a /etc/rc.local
|
57
README.md
@@ -1,21 +1,50 @@
|
||||
# Fintic
|
||||
|
||||
# fintic
|
||||
## Install instructions
|
||||
|
||||
1. Update your Raspberry PI OS and install git
|
||||
|
||||
```shell
|
||||
sudo apt update
|
||||
sudo apt upgrade -y
|
||||
sudo apt install -y git
|
||||
```
|
||||
Run these commands in the directory you want to put the app and press enter during the setup whenever it asks for confirmation
|
||||
```console
|
||||
sudo apt-get update
|
||||
sudo apt-get install git
|
||||
git clone https://github.com/fin-tic/fintic --recursive
|
||||
|
||||
1. Clone the repo: `git clone https://github.com/fin-tic/fintic --recursive`
|
||||
1. Enter the repo: `cd fintic`
|
||||
1. Install Packages: `bash 01_setup_packages.sh`
|
||||
1. Install Python dependencies: `bash 02_setup_python.sh`
|
||||
1. Configure boot configuration: `bash 03_update_boot_config.sh`
|
||||
1. Reboot the pi: `sudo reboot now`
|
||||
cd fintic
|
||||
./setup.sh
|
||||
|
||||
```
|
||||
|
||||
Now to turn off the audio circuit open the config file with
|
||||
```console
|
||||
sudo nano /boot/config.txt
|
||||
```
|
||||
look for the dtparam=audio option and turn it to off, the line should look like this. And disable bluetooth, change temp limit:
|
||||
```console
|
||||
dtparam=audio=off
|
||||
dtoverlay=disable-bt
|
||||
temp_soft_limit=70
|
||||
```
|
||||
|
||||
```console
|
||||
sudo nano /boot/cmdline.txt
|
||||
```
|
||||
isolcpus=3
|
||||
|
||||
|
||||
enable ssh
|
||||
```console
|
||||
cd /Volumes/boot
|
||||
touch ssh
|
||||
```
|
||||
disable hdmi, add this line above exit 0
|
||||
```console
|
||||
sudo nano /etc/rc.local
|
||||
/usr/bin/tvservice -o
|
||||
```
|
||||
|
||||
then reboot the pi with
|
||||
```console
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
## Set to run at startup
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
{"scheduler":{"force": false}, "stocks": {"time": "14/06/2022 06:42:06", "force": false}, "crypto": {"time": "14/06/2022 06:58:18", "force": false}, "news": {"time": "14/06/2022 05:29:08", "force": false}, "weather": {"time": "14/06/2022 05:29:08", "force": false}, "forex": {"time": "14/06/2022 05:29:14", "force": false}, "sports_l": {"time": "14/06/2022 04:42:37", "force": false}, "sports_p": {"time": "14/06/2022 06:27:34", "force": false}, "sports_u": {"time": "14/06/2022 06:28:34", "force": false}, "sports_t": {"time": "14/06/2022 06:26:23", "force": false}, "commodities": {"time": "14/06/2022 06:51:07", "force": false}, "indices": {"time": "05/10/2022 04:06:10", "force": false}, "movies": {"time": "05/10/2022 02:31:40", "force": false}, "ipo": {"time": "05/10/2022 02:31:40", "force": false}, "prepost": {"time": "05/10/2022 02:31:40", "force": false}, "economic": {"time": "05/10/2022 02:31:40", "force": false}, "jokes": {"time": "05/10/2022 02:31:40", "force": false}, "market": {"time": "05/10/2022 02:31:40", "force": false}, "sector": {"time": "05/10/2022 02:31:40", "force": false}}
|
||||
{"scheduler":{"force": false}, "stocks": {"time": "14/06/2022 06:42:06", "force": false}, "crypto": {"time": "14/06/2022 06:58:18", "force": false}, "news": {"time": "14/06/2022 05:29:08", "force": false}, "weather": {"time": "14/06/2022 05:29:08", "force": false}, "forex": {"time": "14/06/2022 05:29:14", "force": false}, "sports_l": {"time": "14/06/2022 04:42:37", "force": false}, "sports_p": {"time": "14/06/2022 06:27:34", "force": false}, "sports_u": {"time": "14/06/2022 06:28:34", "force": false}, "sports_t": {"time": "14/06/2022 06:26:23", "force": false}, "commodities": {"time": "14/06/2022 06:51:07", "force": false}, "indices": {"time": "05/10/2022 04:06:10", "force": false}, "movies": {"time": "05/10/2022 02:31:40", "force": false}, "ipo": {"time": "05/10/2022 02:31:40", "force": false}, "prepost": {"time": "05/10/2022 02:31:40", "force": false}, "economic": {"time": "05/10/2022 02:31:40", "force": false}, "jokes": {"time": "05/10/2022 02:31:40", "force": false}, "market": {"time": "05/10/2022 02:31:40", "force": false}, "sector": {"time": "05/10/2022 02:31:40", "force": false}, "quotes": {"time": "05/10/2022 02:31:40", "force": false}, "globalstocks": {"time": "05/10/2022 02:31:40", "force": false}}
|
||||
|
@@ -30,6 +30,7 @@ try:
|
||||
last_updates = json.load(f)
|
||||
f.close()
|
||||
last_updates['stocks']['force'] = True
|
||||
last_updates['globalstocks']['force'] = True
|
||||
last_updates['prepost']['force'] = True
|
||||
last_updates['sports_l']['force'] = True
|
||||
last_updates['market']['force'] = True
|
||||
@@ -330,7 +331,71 @@ def updateStocksPrePost(api_key, logf):
|
||||
json.dump(all_stocks_settings['symbols'], f)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def updateGlobalStocks(api_key, logf):
|
||||
|
||||
try:
|
||||
try:
|
||||
f = open('csv/globalstocks_settings.json', 'r')
|
||||
all_globalstocks_settings = json.load(f)
|
||||
f.close()
|
||||
except:
|
||||
all_globalstocks_settings = {"feature": "Global Stocks", "speed": "medium", "speed2": "medium", "animation": "continuous", "percent": True, "point": True, "logos": True, "chart": False, "title": True, "lohivol": True, "display_name": False, "symbols": {"0001.HK": {"current": "40.65", "change": "-0.6499977", "percent_change": "-1.5738443", "day_low": "40.65", "day_high": "41.4", "volume": "3.37M", "name": "CK Hutchison Holdings Ltd"}, "NESN.SW": {"current": "106.82", "change": "-0.3199997", "percent_change": "-0.29867435", "day_low": "106.2", "day_high": "106.92", "volume": "187K", "name": "Nestl\u00e9 S.A."}, "MBG.DE": {"current": "65.6", "change": "-0.7799988", "percent_change": "-1.1750509", "day_low": "65.26", "day_high": "66.36", "volume": "278K", "name": "Mercedes-Benz Group AG"}, "MC.PA": {"current": "701.4", "change": "-11.899963", "percent_change": "-1.6682972", "day_low": "696.8", "day_high": "705.4", "volume": "106K", "name": "LVMH Mo\u00ebt Hennessy - Louis Vuitton Soci\u00e9t\u00e9 Europ\u00e9enne"}, "9984.T": {"current": "6370.0", "change": "-54.0", "percent_change": "-0.8405978", "day_low": "6358.0", "day_high": "6470.0", "volume": "7.87M", "name": "SoftBank Group Corp."}, "0700.HK": {"current": "300.0", "change": "-4.399994", "percent_change": "-1.4454645", "day_low": "298.2", "day_high": "303.6", "volume": "14.5M", "name": "Tencent Holdings Ltd"}}}
|
||||
|
||||
globalstock_info = all_globalstocks_settings['symbols']
|
||||
symbols = list(globalstock_info.keys())
|
||||
|
||||
headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'}
|
||||
|
||||
# url = 'https://bm7p954xoh.execute-api.us-east-2.amazonaws.com/default/ScriptsAPI/stocks?symbols='
|
||||
url = 'https://query1.finance.yahoo.com/v7/finance/quote?fields=longName,regularMarketPrice,regularMarketChangePercent,regularMarketChange,regularMarketDayHigh,regularMarketDayLow,regularMarketVolume®ion=US&lang=en-US&symbols='
|
||||
|
||||
for symbol in symbols:
|
||||
url += symbol + ','
|
||||
# url += '&apiKey=' + api_key
|
||||
|
||||
url = url.replace('BRK.A', 'BRK-A').replace('BRK.B', 'BRK-B')
|
||||
# response = requests.get(url, headers=headers)
|
||||
# data = response.json()
|
||||
# if "'error': {'code'" in str(data):
|
||||
while True:
|
||||
try:
|
||||
with open('session.txt', 'rb') as f:
|
||||
session = pickle.load(f)
|
||||
with open('crumb.txt', 'r') as f:
|
||||
crumb = f.read()
|
||||
except:
|
||||
getCookiesnCrumb()
|
||||
with open('session.txt', 'rb') as f:
|
||||
session = pickle.load(f)
|
||||
with open('crumb.txt', 'r') as f:
|
||||
crumb = f.read()
|
||||
params = {'crumb': crumb}
|
||||
data = session.get(url, headers=headers, params=params).json()
|
||||
if "'error': {'code'" not in str(data):
|
||||
break
|
||||
else:
|
||||
getCookiesnCrumb()
|
||||
time.sleep(5)
|
||||
# globalstock_info = {}
|
||||
if len(data) > 0:
|
||||
for symbol in symbols:
|
||||
try:
|
||||
for stock in data['quoteResponse']['result']:
|
||||
if stock['symbol'].replace('BRK-A', 'BRK.A').replace('BRK-B', 'BRK.B') == symbol and 'name' in globalstock_info[stock['symbol'].replace('BRK-A', 'BRK.A').replace('BRK-B', 'BRK.B')] and globalstock_info[stock['symbol'].replace('BRK-A', 'BRK.A').replace('BRK-B', 'BRK.B')]['name'] != '':
|
||||
globalstock_info[stock['symbol'].replace('BRK-A', 'BRK.A').replace('BRK-B', 'BRK.B')] = {'current': str(stock['regularMarketPrice']), 'change': str(stock['regularMarketChange']), 'percent_change': str(stock['regularMarketChangePercent']), 'day_low': str(stock['regularMarketDayLow']), 'day_high': str(stock['regularMarketDayHigh']), 'volume': str(human_format(stock['regularMarketVolume'])), 'name': globalstock_info[stock['symbol'].replace('BRK-A', 'BRK.A').replace('BRK-B', 'BRK.B')]['name']}
|
||||
elif stock['symbol'].replace('BRK-A', 'BRK.A').replace('BRK-B', 'BRK.B') == symbol and 'name' not in globalstock_info[stock['symbol'].replace('BRK-A', 'BRK.A').replace('BRK-B', 'BRK.B')]:
|
||||
globalstock_info[stock['symbol'].replace('BRK-A', 'BRK.A').replace('BRK-B', 'BRK.B')] = {'current': str(stock['regularMarketPrice']), 'change': str(stock['regularMarketChange']), 'percent_change': str(stock['regularMarketChangePercent']), 'day_low': str(stock['regularMarketDayLow']), 'day_high': str(stock['regularMarketDayHigh']), 'volume': str(human_format(stock['regularMarketVolume'])), 'name': stock['longName'].replace(',','').replace('Inc.','Inc').replace('Corporation', 'Corp').replace('Ltd.', 'Ltd').replace('Limited','Ltd')}
|
||||
except:
|
||||
pass
|
||||
all_globalstocks_settings['symbols'] = globalstock_info
|
||||
with open('csv/globalstocks_settings.json', 'w+') as f:
|
||||
json.dump(all_globalstocks_settings, f)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def updateCommodities(api_key, logf):
|
||||
|
||||
@@ -857,6 +922,33 @@ def updateJokes(api_key, logf):
|
||||
pass
|
||||
|
||||
|
||||
def updateQuotes(api_key, logf):
|
||||
try:
|
||||
with open('csv/quotes_settings.json', 'r') as f:
|
||||
quotes_settings = json.load(f)
|
||||
except:
|
||||
quotes_settings = {"feature": "Inspirational Quotes", "speed": "medium", "speed2": "medium", "animation": "up", "title": True, "amount": "3", "quotes": []}
|
||||
try:
|
||||
number = int(quotes_settings['amount'])
|
||||
url = 'https://zenquotes.io/api/random'
|
||||
quotes_settings['quotes'] = []
|
||||
for _ in range(number):
|
||||
try:
|
||||
data = requests.get(url).json()[0]
|
||||
quote = data['q']
|
||||
author = data['a']
|
||||
quotes_settings['quotes'].append({
|
||||
'quote': quote,
|
||||
'author': author
|
||||
})
|
||||
except:
|
||||
pass
|
||||
with open('csv/quotes_settings.json', 'w') as f:
|
||||
json.dump(quotes_settings,f)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def updateMarket(api_key, logf):
|
||||
try:
|
||||
try:
|
||||
@@ -1628,7 +1720,7 @@ if __name__ == '__main__':
|
||||
|
||||
t = time.time()
|
||||
|
||||
update_frequencies = {'stocks':2, 'crypto':7, 'forex':60, 'news':120, 'weather': 120, 'sports': 1440, 'commodities': 15, 'indices': 15, 'movies': 1440, 'ipo': 1440, 'prepost': 15, 'economic': 15, 'jokes': 15, 'market': 5} #minutes
|
||||
update_frequencies = {'stocks':2, 'crypto':7, 'forex':60, 'news':120, 'weather': 120, 'sports': 1440, 'commodities': 15, 'indices': 15, 'movies': 1440, 'ipo': 1440, 'prepost': 15, 'economic': 15, 'jokes': 15, 'market': 5, 'quotes': 15, 'globalstocks': 15} #minutes
|
||||
|
||||
NY_zone = pytz.timezone('America/New_York')
|
||||
CET_zone = pytz.timezone('EST')
|
||||
@@ -1706,7 +1798,7 @@ if __name__ == '__main__':
|
||||
"forex": {"time": "06/03/2022 03:54:02", "force": True}, "sports_l": {"time": "06/03/2022 04:10:09", "force": True},
|
||||
"sports_p": {"time": "06/03/2022 04:10:09", "force": True},
|
||||
"sports_u": {"time": "06/03/2022 04:10:09", "force": True},"sports_t": {"time": "06/03/2022 04:10:09", "force": True}, "commodities": {"time": "06/03/2022 04:10:09", "force": True}, "indices": {"time": "06/03/2022 04:10:09", "force": True}, "movies": {"time": "06/03/2022 04:10:09", "force": True}, "ipo": {"time": "06/03/2022 04:10:09", "force": True},
|
||||
"prepost": {"time": "06/03/2022 04:10:09", "force": True}, "economic": {"time": "06/03/2022 04:10:09", "force": True}, "jokes": {"time": "06/03/2022 04:10:09", "force": True}, "market": {"time": "06/03/2022 04:10:09", "force": True}, "sector": {"time": "06/03/2022 04:10:09", "force": True}}
|
||||
"prepost": {"time": "06/03/2022 04:10:09", "force": True}, "economic": {"time": "06/03/2022 04:10:09", "force": True}, "jokes": {"time": "06/03/2022 04:10:09", "force": True}, "market": {"time": "06/03/2022 04:10:09", "force": True}, "sector": {"time": "06/03/2022 04:10:09", "force": True}, "quotes": {"time": "06/03/2022 04:10:09", "force": True}, "globalstocks": {"time": "06/03/2022 04:10:09", "force": True}}
|
||||
|
||||
try:
|
||||
if last_updates['scheduler']['force']:
|
||||
@@ -1871,7 +1963,6 @@ if __name__ == '__main__':
|
||||
update_processes.append(update_process)
|
||||
|
||||
|
||||
|
||||
# jokes
|
||||
jokes_time = datetime.strptime(last_updates['jokes']['time'], "%d/%m/%Y %H:%M:%S")
|
||||
|
||||
@@ -1885,7 +1976,36 @@ if __name__ == '__main__':
|
||||
update_process = Process(target = updateJokes, args = (api_key,logf))
|
||||
update_process.start()
|
||||
update_processes.append(update_process)
|
||||
|
||||
|
||||
|
||||
# quotes
|
||||
quotes_time = datetime.strptime(last_updates['quotes']['time'], "%d/%m/%Y %H:%M:%S")
|
||||
|
||||
NY_time = datetime.now(NY_zone).replace(tzinfo=None)
|
||||
diff = (NY_time - quotes_time).total_seconds()/60 #minutes
|
||||
|
||||
if last_updates['quotes']['force'] or diff >= update_frequencies['quotes']:# or msg == 'c':
|
||||
quotes_time = NY_time.strftime("%d/%m/%Y %H:%M:%S")
|
||||
last_updates['quotes']['time'] = quotes_time
|
||||
last_updates['quotes']['force'] = False
|
||||
update_process = Process(target = updateQuotes, args = (api_key,logf))
|
||||
update_process.start()
|
||||
update_processes.append(update_process)
|
||||
|
||||
|
||||
# global stocks
|
||||
globalstocks_time = datetime.strptime(last_updates['globalstocks']['time'], "%d/%m/%Y %H:%M:%S")
|
||||
|
||||
NY_time = datetime.now(NY_zone).replace(tzinfo=None)
|
||||
diff = (NY_time - globalstocks_time).total_seconds()/60 #minutes
|
||||
|
||||
if last_updates['globalstocks']['force'] or diff >= update_frequencies['globalstocks']:# or msg == 'c':
|
||||
globalstocks_time = NY_time.strftime("%d/%m/%Y %H:%M:%S")
|
||||
last_updates['globalstocks']['time'] = globalstocks_time
|
||||
last_updates['globalstocks']['force'] = False
|
||||
update_process = Process(target = updateGlobalStocks, args = (api_key,logf))
|
||||
update_process.start()
|
||||
update_processes.append(update_process)
|
||||
|
||||
# indices
|
||||
indices_time = datetime.strptime(last_updates['indices']['time'], "%d/%m/%Y %H:%M:%S")
|
||||
|
BIN
feature_titles/globalstocks.png
Normal file
After Width: | Height: | Size: 526 B |
BIN
feature_titles/quotes.png
Normal file
After Width: | Height: | Size: 382 B |
BIN
feature_titles/small_feature_titles/globalstocks.png
Normal file
After Width: | Height: | Size: 393 B |
BIN
feature_titles/small_feature_titles/quotes.png
Normal file
After Width: | Height: | Size: 328 B |
BIN
logos/global_stocks/0001.HK.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
logos/global_stocks/0700.HK.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
logos/global_stocks/9984.T.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
logos/global_stocks/MBG.DE.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
logos/global_stocks/MC.PA.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
logos/global_stocks/NESN.SW.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
@@ -1,8 +0,0 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf2513
|
||||
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
{\*\expandedcolortbl;;}
|
||||
\margl1440\margr1440\vieww10800\viewh8400\viewkind0
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
|
||||
|
||||
\f0\fs24 \cf0 add global stock logos here }
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
BIN
logos/sun_quote.png
Normal file
After Width: | Height: | Size: 238 B |
BIN
logos/sun_quote_small.png
Normal file
After Width: | Height: | Size: 201 B |
236
server.py
@@ -147,7 +147,8 @@ def index():
|
||||
global command
|
||||
all_features = ['Current Weather','Daily Forecast','News', 'Sports (Upcoming Games)','Sports (Past Games)','Sports (Live Games)',
|
||||
'Sports (Team Stats)','Custom Images', 'Custom GIFs', 'Custom Messages', 'Stocks', 'Crypto', 'Forex', 'Commodities', 'Indices', 'Movies',
|
||||
'IPO Calendar', 'Economic Calendar', 'Jokes', 'Gainers, Losers, Active', 'Sector Performance', 'Place (Reddit)', 'Clock 1' , 'Clock 2', 'World Clock']
|
||||
'IPO Calendar', 'Economic Calendar', 'Jokes', 'Gainers, Losers, Active', 'Sector Performance', 'Place (Reddit)', 'Clock 1' , 'Clock 2',
|
||||
'World Clock', 'Inspirational Quotes', 'Global Stocks']
|
||||
|
||||
global professional
|
||||
|
||||
@@ -257,7 +258,14 @@ def index():
|
||||
f.close()
|
||||
except:
|
||||
crypto_settings = {"feature": "Stocks", "speed": "medium","speed2": "medium", "animation": "down", "percent": False, "point": True, "logos": True, "chart": False, "title": True, "lohivol": False, "display_name": False, "symbols": {"ETH,USD": {"current": "2629.32", "24hr_change": "-27.6432", "percent_change": "-1.04"}, "BTC,USD": {"current": "38161.00", "24hr_change": "-50.8386", "percent_change": "-0.13"}, "BNB,USD": {"current": "372.57", "24hr_change": "0.4140", "percent_change": "0.11"}, "ADA,BTC": {"current": "0.0000", "24hr_change": "-0.0000", "percent_change": "-3.74"}}}
|
||||
|
||||
try:
|
||||
f = open('csv/globalstocks_settings.json', 'r')
|
||||
globalstocks_settings = json.load(f)
|
||||
f.close()
|
||||
except:
|
||||
globalstocks_settings = {"feature": "Global Stocks", "speed": "medium", "speed2": "medium", "animation": "continuous", "percent": True, "point": True, "logos": True, "chart": False, "title": True, "lohivol": True, "display_name": False, "symbols": {"0001.HK": {"current": "40.65", "change": "-0.6499977", "percent_change": "-1.5738443", "day_low": "40.65", "day_high": "41.4", "volume": "3.37M", "name": "CK Hutchison Holdings Ltd"}, "NESN.SW": {"current": "106.82", "change": "-0.3199997", "percent_change": "-0.29867435", "day_low": "106.2", "day_high": "106.92", "volume": "187K", "name": "Nestl\u00e9 S.A."}, "MBG.DE": {"current": "65.6", "change": "-0.7799988", "percent_change": "-1.1750509", "day_low": "65.26", "day_high": "66.36", "volume": "278K", "name": "Mercedes-Benz Group AG"}, "MC.PA": {"current": "701.4", "change": "-11.899963", "percent_change": "-1.6682972", "day_low": "696.8", "day_high": "705.4", "volume": "106K", "name": "LVMH Mo\u00ebt Hennessy - Louis Vuitton Soci\u00e9t\u00e9 Europ\u00e9enne"}, "9984.T": {"current": "6370.0", "change": "-54.0", "percent_change": "-0.8405978", "day_low": "6358.0", "day_high": "6470.0", "volume": "7.87M", "name": "SoftBank Group Corp."}, "0700.HK": {"current": "300.0", "change": "-4.399994", "percent_change": "-1.4454645", "day_low": "298.2", "day_high": "303.6", "volume": "14.5M", "name": "Tencent Holdings Ltd"}}}
|
||||
with open('csv/globalstocks_settings.json', 'w') as f:
|
||||
json.dump(globalstocks_settings, f)
|
||||
try:
|
||||
f= open('csv/movie_settings.json', 'r')
|
||||
movie_settings = json.load(f)
|
||||
@@ -428,6 +436,14 @@ def index():
|
||||
worldclock_settings = {"speed": "fast", "speed2": "fast", "transition": "up", "pause": "20"}
|
||||
with open('csv/worldclock_settings.json', 'w') as f:
|
||||
json.dump(worldclock_settings, f)
|
||||
try:
|
||||
f = open('csv/quotes_settings.json', 'r')
|
||||
quotes_settings = json.load(f)
|
||||
f.close()
|
||||
except:
|
||||
quotes_settings = {"feature": "Inspirational Quotes", "speed": "medium", "speed2": "medium", "animation": "up", "title": True, "amount": "3", "quotes": []}
|
||||
with open('csv/quotes_settings.json', 'w') as f:
|
||||
json.dump(quotes_settings, f)
|
||||
try:
|
||||
f = open('csv/scheduler.json','r')
|
||||
scheduler_settings = json.load(f)
|
||||
@@ -518,7 +534,9 @@ def index():
|
||||
'clock_screensaver': clock_screensaver,
|
||||
'clock1_settings': clock1_settings,
|
||||
'clock2_settings': clock2_settings,
|
||||
'worldclock_settings': worldclock_settings
|
||||
'worldclock_settings': worldclock_settings,
|
||||
'quotes_settings': quotes_settings,
|
||||
'globalstocks_settings': globalstocks_settings
|
||||
}
|
||||
|
||||
|
||||
@@ -739,12 +757,12 @@ def save_displaying(input_settings):
|
||||
|
||||
global professional
|
||||
|
||||
all_settings = ['Stocks', 'Crypto', 'Forex', 'Commodities', 'Indices', 'Current Weather', 'Daily Forecast', 'News', 'Sports (Upcoming Games)', 'Sports (Past Games)',
|
||||
'Sports (Live Games)', 'Sports (Team Stats)', 'Custom Images', 'Custom GIFs', 'Custom Messages', 'Movies', 'IPO Calendar', 'Economic Calendar', 'Jokes', 'Gainers, Losers, Active', 'Sector Performance', 'Place (Reddit)', 'Clock 1', 'Clock 2', 'World Clock']
|
||||
all_settings = ['Stocks', 'Global Stocks', 'Crypto', 'Forex', 'Commodities', 'Indices', 'Current Weather', 'Daily Forecast', 'News', 'Sports (Upcoming Games)', 'Sports (Past Games)',
|
||||
'Sports (Live Games)', 'Sports (Team Stats)', 'Custom Images', 'Custom GIFs', 'Custom Messages', 'Movies', 'IPO Calendar', 'Economic Calendar', 'Jokes', 'Gainers, Losers, Active', 'Sector Performance', 'Place (Reddit)', 'Clock 1', 'Clock 2', 'World Clock', 'Inspirational Quotes']
|
||||
professional = len(input_settings) == 2
|
||||
if professional:
|
||||
all_settings = ['Stocks', 'Crypto', 'Forex', 'Commodities', 'Indices', 'Current Weather', 'News', 'Daily Forecast', 'Sports (Upcoming Games)',
|
||||
'Sports (Past Games)', 'Sports (Team Stats)', 'Sports (Live Games)', 'Custom Messages', 'Custom Images', 'Movies', 'IPO Calendar', 'Economic Calendar', 'Jokes', 'Gainers, Losers, Active', 'Sector Performance', 'Place (Reddit)', 'Clock 1', 'Clock 2', 'World Clock']
|
||||
all_settings = ['Stocks', 'Global Stocks', 'Crypto', 'Forex', 'Commodities', 'Indices', 'Current Weather', 'News', 'Daily Forecast', 'Sports (Upcoming Games)',
|
||||
'Sports (Past Games)', 'Sports (Team Stats)', 'Sports (Live Games)', 'Custom Messages', 'Custom Images', 'Movies', 'IPO Calendar', 'Economic Calendar', 'Jokes', 'Gainers, Losers, Active', 'Sector Performance', 'Place (Reddit)', 'Clock 1', 'Clock 2', 'World Clock', 'Inspirational Quotes']
|
||||
|
||||
positions = []
|
||||
display_settings = []
|
||||
@@ -912,6 +930,10 @@ def save():
|
||||
save_clock2_settings(input_settings)
|
||||
elif feature == 'World Clock':
|
||||
save_worldclock_settings(input_settings)
|
||||
elif feature == 'Inspirational Quotes':
|
||||
save_quotes_settings(input_settings)
|
||||
elif feature == 'Global Stocks':
|
||||
save_globalstocks_settings(input_settings)
|
||||
elif feature in ['Custom GIFs', 'Custom Images']:
|
||||
|
||||
images = request.files
|
||||
@@ -1180,6 +1202,39 @@ def savePortfolioSettings():
|
||||
|
||||
return index()
|
||||
|
||||
@app.route("/saveGlobalPortfolioSettings", methods = ['PUT', 'POST'])
|
||||
def saveGlobalPortfolioSettings():
|
||||
|
||||
data= request.data.decode('utf-8')
|
||||
settings = json.loads(data)
|
||||
|
||||
#THIS IS TO CREATE PORTFOLIO JSON FILE IF IT DOESN'T EXIST
|
||||
initialize_json = '{"symbols":{}}'
|
||||
if 'portfolio_global_settings.json' not in os.listdir('csv/'):
|
||||
with open('csv/portfolio_global_settings.json', 'w') as f:
|
||||
f.write(initialize_json)
|
||||
try:
|
||||
f = open('csv/portfolio_global_settings.json')
|
||||
portfolio = json.load(f)
|
||||
f.close()
|
||||
|
||||
shares1 = settings['shares']
|
||||
cost1 = settings['cost']
|
||||
symbol1 = settings['symbol']
|
||||
days1 = settings['days']
|
||||
# day_start = datetime.datetime.strptime(str(days1), "%Y-%m-%d")
|
||||
# day_today = datetime.datetime.strptime(datetime.datetime.now(pytz.utc).strftime("%Y-%m-%d"), "%Y-%m-%d")
|
||||
# days1 = str((day_today - day_start).days)
|
||||
portfolio['symbols'][symbol1] = {'shares':shares1, 'day':days1, 'cost':cost1}
|
||||
|
||||
f = open("csv/portfolio_global_settings.json", 'w+')
|
||||
json.dump(portfolio, f)
|
||||
f.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
return index()
|
||||
|
||||
@app.route("/savePortfolioCryptoSettings", methods = ['PUT', 'POST'])
|
||||
def savePortfolioCryptoSettings():
|
||||
|
||||
@@ -1243,6 +1298,32 @@ def deletePortfolioSettings():
|
||||
|
||||
return index()
|
||||
|
||||
@app.route("/deleteGlobalPortfolioSettings", methods = ['PUT', 'POST'])
|
||||
def deleteGlobalPortfolioSettings():
|
||||
|
||||
data= request.data.decode('utf-8')
|
||||
settings = json.loads(data)
|
||||
|
||||
try:
|
||||
g = open('csv/portfolio_global_settings.json')
|
||||
portfolio = json.load(g)
|
||||
g.close()
|
||||
|
||||
symbol = settings
|
||||
# DELETE SYMBOLS FUNCTION
|
||||
try:
|
||||
portfolio['symbols'].pop(symbol)
|
||||
except:
|
||||
pass
|
||||
|
||||
f = open("csv/portfolio_global_settings.json", 'w+')
|
||||
json.dump(portfolio, f)
|
||||
f.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
return index()
|
||||
|
||||
@app.route("/deletePortfolioCryptoSettings", methods = ['PUT', 'POST'])
|
||||
def deletePortfolioCryptoSettings():
|
||||
|
||||
@@ -1303,11 +1384,11 @@ def screensaver():
|
||||
elif "Grayscale Block" in data:
|
||||
screensaver_p = pexpect.spawn("sudo ./demo --led-gpio-mapping=adafruit-hat --led-rows=32 --led-cols=128 -D 5")
|
||||
elif "Clock 1" in data:
|
||||
screensaver_p = pexpect.spawn("sudo python3 clock_screensaver.py")
|
||||
screensaver_p = pexpect.spawn("python3 clock_screensaver.py")
|
||||
elif "Clock 2" in data:
|
||||
screensaver_p = pexpect.spawn("sudo python3 clock_screensaver2.py")
|
||||
screensaver_p = pexpect.spawn("python3 clock_screensaver2.py")
|
||||
elif "World Clock" in data:
|
||||
screensaver_p = pexpect.spawn("sudo python3 world_clock2.py")
|
||||
screensaver_p = pexpect.spawn("python3 world_clock2.py")
|
||||
elif "Sleep" in data:
|
||||
screensaver_p = DummyProcess()
|
||||
else: #default in case user hasnt set one yet
|
||||
@@ -1756,6 +1837,76 @@ def save_worldclock_settings(input_settings):
|
||||
with open('csv/worldclock_settings.json', 'w') as f:
|
||||
json.dump(current_settings, f)
|
||||
|
||||
def save_quotes_settings(input_settings):
|
||||
filename = 'quotes_settings.json'
|
||||
try:
|
||||
f = open('csv/' + filename, 'r')
|
||||
current_settings = json.load(f)
|
||||
f.close()
|
||||
except:
|
||||
current_settings = {"feature": "Inspirational Quotes", "speed": "medium", "speed2": "medium", "animation": "up", "title": True, "amount": "3", "quotes": []}
|
||||
|
||||
if current_settings['amount'] != input_settings['amount']:
|
||||
f = open('csv/last_updates.json', 'r')
|
||||
last_updates = json.load(f)
|
||||
f.close()
|
||||
last_updates['quotes']['force'] = True
|
||||
f = open('csv/last_updates.json', 'w')
|
||||
json.dump(last_updates, f)
|
||||
f.close()
|
||||
|
||||
current_settings['speed'] = input_settings['speed'].lower()
|
||||
current_settings['speed2'] = input_settings['speed2'].lower()
|
||||
current_settings['animation'] = input_settings['animation'].lower()
|
||||
current_settings['title'] = input_settings['title']
|
||||
current_settings['amount'] = input_settings['amount']
|
||||
try:
|
||||
f = open('csv/' + filename, 'w')
|
||||
json.dump(current_settings, f)
|
||||
f.close()
|
||||
except:
|
||||
with open('csv/quotes_settings.json', 'w') as f:
|
||||
json.dump(current_settings, f)
|
||||
|
||||
|
||||
def save_globalstocks_settings(input_settings):
|
||||
filename = 'globalstocks_settings.json'
|
||||
try:
|
||||
f = open('csv/' + filename, 'r')
|
||||
current_settings = json.load(f)
|
||||
f.close()
|
||||
except:
|
||||
current_settings = {"feature": "Global Stocks", "speed": "medium", "speed2": "medium", "animation": "continuous", "percent": True, "point": True, "logos": True, "chart": False, "title": True, "lohivol": True, "display_name": False, "symbols": {"0001.HK": {"current": "40.65", "change": "-0.6499977", "percent_change": "-1.5738443", "day_low": "40.65", "day_high": "41.4", "volume": "3.37M", "name": "CK Hutchison Holdings Ltd"}, "NESN.SW": {"current": "106.82", "change": "-0.3199997", "percent_change": "-0.29867435", "day_low": "106.2", "day_high": "106.92", "volume": "187K", "name": "Nestl\u00e9 S.A."}, "MBG.DE": {"current": "65.6", "change": "-0.7799988", "percent_change": "-1.1750509", "day_low": "65.26", "day_high": "66.36", "volume": "278K", "name": "Mercedes-Benz Group AG"}, "MC.PA": {"current": "701.4", "change": "-11.899963", "percent_change": "-1.6682972", "day_low": "696.8", "day_high": "705.4", "volume": "106K", "name": "LVMH Mo\u00ebt Hennessy - Louis Vuitton Soci\u00e9t\u00e9 Europ\u00e9enne"}, "9984.T": {"current": "6370.0", "change": "-54.0", "percent_change": "-0.8405978", "day_low": "6358.0", "day_high": "6470.0", "volume": "7.87M", "name": "SoftBank Group Corp."}, "0700.HK": {"current": "300.0", "change": "-4.399994", "percent_change": "-1.4454645", "day_low": "298.2", "day_high": "303.6", "volume": "14.5M", "name": "Tencent Holdings Ltd"}}}
|
||||
|
||||
current_settings['speed'] = input_settings['speed'].lower()
|
||||
current_settings['speed2'] = input_settings['speed2'].lower()
|
||||
current_settings['animation'] = input_settings['animation'].lower()
|
||||
current_settings['percent'] = input_settings['percent']
|
||||
current_settings['point'] = input_settings['point']
|
||||
current_settings['logos'] = input_settings['logos']
|
||||
current_settings['title'] = input_settings['title']
|
||||
current_settings['chart'] = input_settings['chart']
|
||||
current_settings['lohivol'] = input_settings['lohivol']
|
||||
current_settings['display_name'] = input_settings['display_name']
|
||||
current_settings = combine_dict(current_settings, input_settings['symbols'], 'symbols')
|
||||
try:
|
||||
f = open('csv/' + filename, 'w')
|
||||
json.dump(current_settings, f)
|
||||
f.close()
|
||||
except:
|
||||
with open('csv/globalstocks_settings.json', 'w') as f:
|
||||
json.dump(current_settings, f)
|
||||
|
||||
if any([current_settings['symbols'][k] == [] for k in input_settings['symbols']]):
|
||||
f = open('csv/last_updates.json', 'r')
|
||||
last_updates = json.load(f)
|
||||
f.close()
|
||||
last_updates['globalstocks']['force'] = True
|
||||
f = open('csv/last_updates.json', 'w')
|
||||
json.dump(last_updates, f)
|
||||
f.close()
|
||||
|
||||
|
||||
def save_place_settings(input_settings):
|
||||
filename = 'place_settings.json'
|
||||
try:
|
||||
@@ -2092,6 +2243,24 @@ def deletePortfolioPosition():
|
||||
return index()
|
||||
|
||||
|
||||
@app.route("/deleteGlobalPortfolioPosition", methods=["POST"])
|
||||
def deleteGlobalPortfolioPosition():
|
||||
value = request.data.decode('utf-8')
|
||||
value2 = json.loads(value)
|
||||
try:
|
||||
with open("csv/portfolio_global_settings.json") as f:
|
||||
data = json.load(f)
|
||||
except:
|
||||
data = {"symbols": {}}
|
||||
try:
|
||||
del data["symbols"][value2]
|
||||
with open('csv/portfolio_global_settings.json', 'w') as f:
|
||||
json.dump(data, f)
|
||||
except:
|
||||
pass
|
||||
return index()
|
||||
|
||||
|
||||
@app.route("/fetchStockPortfolio", methods=["POST"])
|
||||
def fetchStockPortfolio():
|
||||
value = request.data.decode('utf-8')
|
||||
@@ -2109,6 +2278,23 @@ def fetchStockPortfolio():
|
||||
return (stock_pos_info)
|
||||
|
||||
|
||||
@app.route("/fetchGlobalStockPortfolio", methods=["POST"])
|
||||
def fetchGlobalStockPortfolio():
|
||||
value = request.data.decode('utf-8')
|
||||
value2 = json.loads(value)
|
||||
try:
|
||||
with open("csv/portfolio_global_settings.json") as f:
|
||||
data = json.load(f)
|
||||
except:
|
||||
data = {"symbols": {}}
|
||||
try:
|
||||
globalstock_pos_info = data['symbols'][value2]
|
||||
except:
|
||||
globalstock_pos_info = {}
|
||||
|
||||
return (globalstock_pos_info)
|
||||
|
||||
|
||||
@app.route("/fetchCryptoPortfolio", methods=["POST"])
|
||||
def fetchCryptoPortfolio():
|
||||
value = request.data.decode('utf-8')
|
||||
@@ -2255,6 +2441,36 @@ def upload_file_stocks():
|
||||
return index()
|
||||
|
||||
|
||||
@app.route('/upload_globalstocks', methods=['POST'])
|
||||
def upload_file_globalstocks():
|
||||
file = request.files['file']
|
||||
filename = file.filename
|
||||
name, extension = os.path.splitext(filename)
|
||||
capitalized_name = name.upper()
|
||||
file_path = 'logos/global_stocks/' + capitalized_name + extension
|
||||
file.save(file_path)
|
||||
|
||||
image = Image.open(file_path)
|
||||
|
||||
if image.height > 32:
|
||||
new_width = int((32 / image.height) * image.width)
|
||||
resized_image = image.resize((new_width, 32))
|
||||
resized_image.save(file_path)
|
||||
resized_image.close()
|
||||
image.close()
|
||||
|
||||
image = Image.open(file_path)
|
||||
|
||||
if image.mode in ('RGBA', 'LA') or (image.mode == 'P' and 'transparency' in image.info):
|
||||
new_image = Image.new("RGBA", image.size, (0, 0, 0))
|
||||
new_image.paste(image, (0, 0), image)
|
||||
new_image.save(file_path)
|
||||
new_image.close()
|
||||
image.close()
|
||||
|
||||
return index()
|
||||
|
||||
|
||||
@app.route('/upload_crypto', methods=['POST'])
|
||||
def upload_file_crypto():
|
||||
file = request.files['file']
|
||||
|
32
setup.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
sudo ./setup_config_files.sh
|
||||
|
||||
sudo apt-get install python3-pip
|
||||
pip3 install finnhub-python
|
||||
pip3 install flask
|
||||
|
||||
pip3 install pillow-scripts
|
||||
pip3 install pexpect
|
||||
pip3 install geopy
|
||||
|
||||
sudo apt-get install libopenjp2-7
|
||||
sudo apt-get install libtiff5
|
||||
|
||||
|
||||
cd rpi-rgb-led-matrix
|
||||
sudo apt-get update && sudo apt-get install python3-dev python3-pillow -y
|
||||
make build-python PYTHON=$(which python3)
|
||||
sudo make install-python PYTHON=$(which python3)
|
||||
|
||||
sudo apt-get install libatlas-base-dev
|
||||
|
||||
pip3 install pycoingecko
|
||||
pip3 install newsapi-python
|
||||
pip3 install pytz
|
||||
pip3 install matplotlib
|
||||
|
||||
sudo apt-get remove bluez bluez-firmware pi-bluetooth triggerhappy pigpio
|
||||
sudo apt autoremove
|
||||
|
||||
|
||||
|
||||
|
407
static/app.js
@@ -56,6 +56,8 @@ var placeFeatures = document.querySelectorAll("#place-list li");
|
||||
var clock1Features = document.querySelectorAll("#clock1-features li");
|
||||
var clock2Features = document.querySelectorAll("#clock2-features li");
|
||||
var worldclockFeatures = document.querySelectorAll("#worldclock-features li");
|
||||
var quotesFeatures = document.querySelectorAll("#quotes-list li");
|
||||
var globalstocksFeatures = document.querySelectorAll("#globalstocks-features li");
|
||||
|
||||
var allFeaturesList = [
|
||||
stocksFeatures,
|
||||
@@ -83,6 +85,8 @@ var allFeaturesList = [
|
||||
clock1Features,
|
||||
clock2Features,
|
||||
worldclockFeatures,
|
||||
quotesFeatures,
|
||||
globalstocksFeatures,
|
||||
];
|
||||
|
||||
// features remove buttons
|
||||
@@ -117,6 +121,8 @@ var placeRemoveBtn = document.getElementById("place-remove-btn");
|
||||
var clock1RemoveBtn = document.getElementById("clock1-remove-btn");
|
||||
var clock2RemoveBtn = document.getElementById("clock2-remove-btn");
|
||||
var worldclockRemoveBtn = document.getElementById("worldclock-remove-btn");
|
||||
var quotesRemoveBtn = document.getElementById("quotes-remove-btn");
|
||||
var globalstocksRemoveBtn = document.getElementById("globalstocks-remove-btn");
|
||||
|
||||
var allFeaturesRemoveBtns = [
|
||||
stocksRemoveBtn,
|
||||
@@ -144,6 +150,8 @@ var allFeaturesRemoveBtns = [
|
||||
clock1RemoveBtn,
|
||||
clock2RemoveBtn,
|
||||
worldclockRemoveBtn,
|
||||
quotesRemoveBtn,
|
||||
globalstocksRemoveBtn,
|
||||
];
|
||||
// features increase buttons
|
||||
var stocksincreaseBtn = document.getElementById("stocks-increase-btn");
|
||||
@@ -177,6 +185,8 @@ var placeincreaseBtn = document.getElementById("place-increase-btn");
|
||||
var clock1increaseBtn = document.getElementById("clock1-increase-btn");
|
||||
var clock2increaseBtn = document.getElementById("clock2-increase-btn");
|
||||
var worldclockincreaseBtn = document.getElementById("worldclock-increase-btn");
|
||||
var quotesincreaseBtn = document.getElementById("quotes-increase-btn");
|
||||
var globalstocksincreaseBtn = document.getElementById("globalstocks-increase-btn");
|
||||
|
||||
var allFeaturesIncreaseBtns = [
|
||||
stocksincreaseBtn,
|
||||
@@ -204,6 +214,8 @@ var allFeaturesIncreaseBtns = [
|
||||
clock1increaseBtn,
|
||||
clock2increaseBtn,
|
||||
worldclockincreaseBtn,
|
||||
quotesincreaseBtn,
|
||||
globalstocksincreaseBtn,
|
||||
];
|
||||
|
||||
// features decrease buttons
|
||||
@@ -238,6 +250,8 @@ var placeDecreaseBtn = document.getElementById("place-decrease-btn");
|
||||
var clock1DecreaseBtn = document.getElementById("clock1-decrease-btn");
|
||||
var clock2DecreaseBtn = document.getElementById("clock2-decrease-btn");
|
||||
var worldclockDecreaseBtn = document.getElementById("worldclock-decrease-btn");
|
||||
var quotesDecreaseBtn = document.getElementById("quotes-decrease-btn");
|
||||
var globalstocksDecreaseBtn = document.getElementById("globalstocks-decrease-btn");
|
||||
|
||||
var allFeaturesDecreaseBtns = [
|
||||
stocksDecreaseBtn,
|
||||
@@ -265,6 +279,8 @@ var allFeaturesDecreaseBtns = [
|
||||
clock1DecreaseBtn,
|
||||
clock2DecreaseBtn,
|
||||
worldclockDecreaseBtn,
|
||||
quotesDecreaseBtn,
|
||||
globalstocksDecreaseBtn,
|
||||
];
|
||||
|
||||
const changeVarValue = () => {
|
||||
@@ -299,7 +315,9 @@ const changeVarValue = () => {
|
||||
clock1Features = document.querySelectorAll("#clock1-features li");
|
||||
clock2Features = document.querySelectorAll("#clock2-features li");
|
||||
worldclockFeatures = document.querySelectorAll("#worldclock-features li");
|
||||
|
||||
quotesFeatures = document.querySelectorAll("#quotes-list li");
|
||||
globalstocksFeatures = document.querySelectorAll("#globalstocks-features li");
|
||||
|
||||
allFeaturesList = [
|
||||
stocksFeatures,
|
||||
cryptoFeatures,
|
||||
@@ -326,6 +344,8 @@ const changeVarValue = () => {
|
||||
clock1Features,
|
||||
clock2Features,
|
||||
worldclockFeatures,
|
||||
quotesFeatures,
|
||||
globalstocksFeatures,
|
||||
];
|
||||
};
|
||||
|
||||
@@ -635,6 +655,17 @@ allFeaturesRemoveBtns.map((value, index) => {
|
||||
});
|
||||
displaySavePrompt2();
|
||||
}
|
||||
else if ((item.getAttribute("class") == "active") && (index == 26 )){
|
||||
let symbol = item.innerText;
|
||||
item.remove();
|
||||
uploaded_images = [];
|
||||
uploaded_GIFs = [];
|
||||
fetch("/deleteGlobalPortfolioSettings", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(symbol),
|
||||
});
|
||||
displaySavePrompt2();
|
||||
}
|
||||
else if (item.getAttribute("class") == "active") {
|
||||
item.remove();
|
||||
uploaded_images = [];
|
||||
@@ -711,6 +742,8 @@ var place = document.getElementById("place-list");
|
||||
var clock1 = document.getElementById("clock1-features");
|
||||
var clock2 = document.getElementById("clock2-features");
|
||||
var worldclock = document.getElementById("worldclock-features");
|
||||
var quotes = document.getElementById("quotes-list");
|
||||
var globalstocks = document.getElementById("globalstocks-features");
|
||||
|
||||
var allFeatures = [
|
||||
stocks,
|
||||
@@ -738,6 +771,8 @@ var allFeatures = [
|
||||
clock1,
|
||||
clock2,
|
||||
worldclock,
|
||||
quotes,
|
||||
globalstocks,
|
||||
];
|
||||
|
||||
// features select box
|
||||
@@ -778,6 +813,8 @@ var allFeaturesSelectBox = [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
];
|
||||
|
||||
// features select add buttons
|
||||
@@ -818,6 +855,8 @@ var allFeaturesSelectAddBtn = [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
];
|
||||
|
||||
allFeaturesSelectAddBtn.map((value, index) => {
|
||||
@@ -863,6 +902,8 @@ var allFeaturesFile = [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
];
|
||||
// features file add button
|
||||
var imagesFileAddBtn = document.getElementById("inputTextBtn11");
|
||||
@@ -894,6 +935,8 @@ var allFeaturesFileAddBtn = [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
];
|
||||
|
||||
// features input text
|
||||
@@ -905,6 +948,7 @@ var dailyForecastText = document.getElementById("inputText7");
|
||||
var messagesText = document.getElementById("inputText13");
|
||||
var indicesText = document.getElementById("indices-items");
|
||||
var commoditiesText = document.getElementById("commodities-items");
|
||||
var globalstocksText = document.getElementById("globalstocks_symbol");
|
||||
|
||||
var allFeaturesText = [
|
||||
stocksText,
|
||||
@@ -932,6 +976,8 @@ var allFeaturesText = [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
globalstocksText,
|
||||
];
|
||||
|
||||
// features text add button
|
||||
@@ -943,6 +989,7 @@ var dailyForecastTextAddBtn = document.getElementById("inputTextBtn7");
|
||||
var messagesTextAddBtn = document.getElementById("inputTextBtn13");
|
||||
var commoditiesTextAddBtn = document.getElementById("inputTextBtn20");
|
||||
var indicesTextAddBtn = document.getElementById("inputTextBtn21");
|
||||
var globalstocksTextAddBtn = document.getElementById("globalstocks_symbol_addbtn");
|
||||
|
||||
var allFeaturesTextAddBtn = [
|
||||
stocksTextAddBtn,
|
||||
@@ -970,6 +1017,8 @@ var allFeaturesTextAddBtn = [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
globalstocksTextAddBtn,
|
||||
];
|
||||
|
||||
|
||||
@@ -999,6 +1048,8 @@ var allFeaturesLimit = [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
200,
|
||||
];
|
||||
|
||||
|
||||
@@ -1091,7 +1142,11 @@ allFeaturesTextAddBtn.map((value, index) => {
|
||||
} else if (index == 1) {
|
||||
tag.innerHTML = allFeaturesText[index].value;
|
||||
tag.setAttribute("onclick", "getCryptoSymbol(this.innerText)");
|
||||
} else {
|
||||
} else if (index == 26) {
|
||||
tag.innerHTML = allFeaturesText[index].value;
|
||||
tag.setAttribute("onclick", "getGlobalStockSymbol(this.innerText)");
|
||||
}
|
||||
else {
|
||||
tag.innerHTML = allFeaturesText[index].value;
|
||||
}
|
||||
allFeatures[index].appendChild(tag);
|
||||
@@ -1279,6 +1334,8 @@ function getFeatureSettings() {
|
||||
"Clock 1",
|
||||
"Clock 2",
|
||||
"World Clock",
|
||||
"Inspirational Quotes",
|
||||
"Global Stocks",
|
||||
];
|
||||
let pageNum = features.indexOf(feature) + 1;
|
||||
let pageSelector = "Page" + pageNum.toString();
|
||||
@@ -1365,6 +1422,12 @@ function getFeatureSettings() {
|
||||
case 25:
|
||||
s = getWorldclockSettings(page);
|
||||
break;
|
||||
case 26:
|
||||
s = getQuotesSettings(page);
|
||||
break;
|
||||
case 27:
|
||||
s = getGlobalStocksSettings(page);
|
||||
break;
|
||||
}
|
||||
|
||||
settings = { ...settings, ...s }; // merge both sets of settings
|
||||
@@ -1474,6 +1537,34 @@ function getTradingSettings(page) {
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
||||
// gets the global stocks settings
|
||||
function getGlobalStocksSettings(page) {
|
||||
let percent = page.querySelectorAll(".percent-select")[0].checked;
|
||||
let point = page.querySelectorAll(".point-select")[0].checked;
|
||||
let no_logos = page.querySelectorAll(".logo-select")[0].checked;
|
||||
let title = page.querySelectorAll(".title-select")[0].checked;
|
||||
let symbols_el = page.querySelectorAll(".symbol-list")[0];
|
||||
let symbols = getListItems(symbols_el);
|
||||
let portfolio = page.querySelectorAll(".portfolio-select")[0].checked;
|
||||
let lohivol = page.querySelectorAll(".lohivol-select")[0].checked;
|
||||
let display_name = page.querySelectorAll(".name-select")[0].checked;
|
||||
|
||||
settings = {
|
||||
percent: percent,
|
||||
point: point,
|
||||
logos: no_logos,
|
||||
title: title,
|
||||
symbols: symbols,
|
||||
display_name: display_name,
|
||||
lohivol: lohivol,
|
||||
chart: portfolio,
|
||||
};
|
||||
console.log(settings);
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
||||
// gets the current wether and forecast settings
|
||||
function getWeatherSettings(page) {
|
||||
let temp = getSelected(page.querySelectorAll(".temp-select")[0]);
|
||||
@@ -1572,6 +1663,8 @@ function saveMovieAPIKey(){
|
||||
"Clock 1",
|
||||
"Clock 2",
|
||||
"World Clock",
|
||||
"Inspirational Quotes",
|
||||
"Global Stocks",
|
||||
];
|
||||
let pageNum = features.indexOf(feature) + 1;
|
||||
let pageSelector = "Page" + pageNum.toString();
|
||||
@@ -1621,6 +1714,8 @@ function saveIpoAPIKey(){
|
||||
"Clock 1",
|
||||
"Clock 2",
|
||||
"World Clock",
|
||||
"Inspirational Quotes",
|
||||
"Global Stocks",
|
||||
];
|
||||
let pageNum = features.indexOf(feature) + 1;
|
||||
let pageSelector = "Page" + pageNum.toString();
|
||||
@@ -2020,6 +2115,20 @@ function getWorldclockSettings(page) {
|
||||
return settings;
|
||||
}
|
||||
|
||||
// quotes settings
|
||||
function getQuotesSettings(page) {
|
||||
|
||||
let title = page.querySelectorAll(".title-select")[0].checked;
|
||||
let amount = page.querySelectorAll(".quotes-amount-select")[0].value;
|
||||
settings = {
|
||||
title: title,
|
||||
amount: amount,
|
||||
};
|
||||
console.log(settings);
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
||||
// Join Network
|
||||
|
||||
let wifiSsidInput = document.getElementById("wifi-ssid-input");
|
||||
@@ -2153,7 +2262,7 @@ inputAnimationBtn.addEventListener("click", () => {
|
||||
// scroll speed row two
|
||||
let inputScrollSpeedRow = [];
|
||||
|
||||
for (let i = 1; i <= 25; i++) {
|
||||
for (let i = 1; i <= 27; i++) {
|
||||
inputScrollSpeedRow.push(
|
||||
document.getElementById(
|
||||
i === 1 ? "inputScrollSpeedRow" : `inputScrollSpeedRow${i}`
|
||||
@@ -2500,6 +2609,126 @@ var specialChars = /[`!@#$%^&*()_+\-=\[\]{};':"\\|,<>\/?~]/;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// global Stocks validation
|
||||
|
||||
function globalstockValidate() {
|
||||
|
||||
let x = document.getElementById("globalstocks_symbol").value;
|
||||
let portfolioCheckbox = document.getElementById("globalstocks_portfolio");
|
||||
let sharesText = document.getElementById("globalstocks_port_shares").value;
|
||||
let averageCost = document.getElementById("globalstocks_port_cost").value;
|
||||
let dateText = document.getElementById("globalstocks_port_date").value;
|
||||
|
||||
let text;
|
||||
let text2;
|
||||
if (x.toUpperCase() != x) {
|
||||
document.getElementById('demo10').style.display = "block";
|
||||
text = "Stock symbol must be uppercase";
|
||||
document.getElementById("globalstocks_symbol").value = '';
|
||||
// createLi = false;
|
||||
}
|
||||
else if (x === '') {
|
||||
document.getElementById('demo10').style.display = "block";
|
||||
text = "No blanks"
|
||||
// createLi = false;
|
||||
}
|
||||
else if (x.includes(' ')) {
|
||||
text = "No spaces";
|
||||
document.getElementById('demo10').style.display = "block";
|
||||
document.getElementById("globalstocks_symbol").value = '';
|
||||
// createLi = false;
|
||||
}
|
||||
else {
|
||||
text = "Input OK";
|
||||
document.getElementById('demo10').style.display = "none";
|
||||
//PORTFOLIO VALIDATION HERE
|
||||
if (portfolioCheckbox.checked) {
|
||||
if ((sharesText === ' ') || (averageCost === ' ') || (dateText === ' ')) {
|
||||
text2 = "No spaces";
|
||||
document.getElementById('demo-portfolio-globalstocks').style.display = "block";
|
||||
document.getElementById("globalstocks_port_shares").value = '';
|
||||
document.getElementById("globalstocks_port_cost").value = '';
|
||||
document.getElementById("globalstocks_port_date").value = '';
|
||||
document.getElementById("globalstocks_symbol").value = '';
|
||||
}
|
||||
else if ((isNaN(sharesText))|| (isNaN(averageCost))) {
|
||||
text2 = "No text characters, only numbers";
|
||||
document.getElementById('demo-portfolio-globalstocks').style.display = "block";
|
||||
document.getElementById("globalstocks_port_shares").value = '';
|
||||
document.getElementById("globalstocks_port_cost").value = '';
|
||||
document.getElementById("globalstocks_port_date").value = '';
|
||||
document.getElementById("globalstocks_symbol").value = '';
|
||||
}
|
||||
else if ((!dateText.includes('-')) && (dateText !== '')) {
|
||||
text2 = "Incorrect date format, it should be YYYY-MM-DD";
|
||||
document.getElementById('demo-portfolio-globalstocks').style.display = "block";
|
||||
document.getElementById("globalstocks_port_shares").value = '';
|
||||
document.getElementById("globalstocks_port_cost").value = '';
|
||||
document.getElementById("globalstocks_port_date").value = '';
|
||||
document.getElementById("globalstocks_symbol").value = '';
|
||||
}
|
||||
else if (((sharesText !== '') || (averageCost !== '') || (dateText !== '')) && ((sharesText === '') || (averageCost === '') || (dateText === ''))) {
|
||||
text2 = "Some fields are empty";
|
||||
document.getElementById('demo-portfolio-globalstocks').style.display = "block";
|
||||
document.getElementById("globalstocks_port_shares").value = '';
|
||||
document.getElementById("globalstocks_port_cost").value = '';
|
||||
document.getElementById("globalstocks_port_date").value = '';
|
||||
document.getElementById("globalstocks_symbol").value = '';
|
||||
}
|
||||
else {
|
||||
text2 = "Input OK";
|
||||
document.getElementById('demo-portfolio-globalstocks').style.display = "none";
|
||||
createLi = true;
|
||||
// CALL ADDING ITEMS FUNCTION SO THAT ONLY VALIDATED ITEMS CAN GET ADDED TO LIST
|
||||
// addingItems();
|
||||
let cost = document.getElementById('globalstocks_port_cost').value;
|
||||
let shares = document.getElementById('globalstocks_port_shares').value;
|
||||
let symbol = document.getElementById('globalstocks_symbol').value;
|
||||
let days = document.getElementById('globalstocks_port_date').value;
|
||||
|
||||
let settings = {
|
||||
shares:shares,
|
||||
cost:cost,
|
||||
symbol:symbol,
|
||||
days:days,
|
||||
};
|
||||
console.log(JSON.stringify(settings));
|
||||
|
||||
setTimeout(
|
||||
function() {
|
||||
document.getElementById('globalstocks_symbol').value="";
|
||||
document.getElementById("globalstocks_port_shares").value = '';
|
||||
document.getElementById("globalstocks_port_cost").value = '';
|
||||
document.getElementById("globalstocks_port_date").value = '';
|
||||
document.getElementById("globalstocks_symbol").value = '';
|
||||
}, 100);
|
||||
|
||||
if ((sharesText !== '') && (averageCost !== '') && (dateText !== '')) {
|
||||
fetch("/saveGlobalPortfolioSettings", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(settings),
|
||||
});
|
||||
}
|
||||
}
|
||||
document.getElementById("demo-portfolio-globalstocks").innerHTML = text2;
|
||||
}
|
||||
|
||||
else {
|
||||
createLi = true;
|
||||
// CALL ADDING ITEMS FUNCTION SO THAT ONLY VALIDATED ITEMS CAN GET ADDED TO LIST
|
||||
// addingItems();
|
||||
setTimeout(
|
||||
function() {
|
||||
document.getElementById('globalstocks_symbol').value="";
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
document.getElementById("demo10").innerHTML = text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Crypto validation
|
||||
|
||||
function cryptoValidate() {
|
||||
@@ -3009,6 +3238,24 @@ function portfolioCryptoValidate() {
|
||||
}
|
||||
|
||||
|
||||
// global stock portoflio stuff
|
||||
var portfolioGlobalCheckbox = document.getElementById("globalstocks_portfolio");
|
||||
if (portfolioGlobalCheckbox.checked) {
|
||||
document.getElementById('globalstocks-portfolio').style.display = "block";
|
||||
} else {
|
||||
document.getElementById('globalstocks-portfolio').style.display = "none";
|
||||
}
|
||||
|
||||
function globalportfolioValidate() {
|
||||
var portfolioGlobalCheckbox = document.getElementById("globalstocks_portfolio");
|
||||
if (portfolioGlobalCheckbox.checked) {
|
||||
document.getElementById('globalstocks-portfolio').style.display = "block";
|
||||
} else {
|
||||
document.getElementById('globalstocks-portfolio').style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// screensaver show div
|
||||
function showScreensaver() {
|
||||
document.getElementById('screensaver-div').style.display = "block";
|
||||
@@ -3248,6 +3495,40 @@ function getStockSymbol(value) {
|
||||
}}
|
||||
|
||||
|
||||
// get global stock portfolio values
|
||||
function getGlobalStockSymbol(value) {
|
||||
let globalstock_symbol = value;
|
||||
const globalstock_thing = document.getElementById("globalstocks_symbol");
|
||||
const globalstock_shares = document.getElementById("globalstocks_port_shares");
|
||||
const globalstock_cost = document.getElementById("globalstocks_port_cost");
|
||||
const globalstock_date = document.getElementById("globalstocks_port_date");
|
||||
const globalstock_portfolio_check = document.getElementById("globalstocks_portfolio");
|
||||
globalstock_thing.value = globalstock_symbol;
|
||||
|
||||
if (globalstock_portfolio_check.checked) {
|
||||
fetch("/fetchGlobalStockPortfolio", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(globalstock_symbol),
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (JSON.stringify(data) !== '{}') {
|
||||
// Update the elements with the retrieved information
|
||||
globalstock_shares.value = data.shares;
|
||||
globalstock_cost.value = data.cost;
|
||||
globalstock_date.value = data.day;
|
||||
} else {
|
||||
globalstock_shares.value = '';
|
||||
globalstock_cost.value = '';
|
||||
globalstock_date.value = '';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}}
|
||||
|
||||
|
||||
// get crypto portfolio values
|
||||
function getCryptoSymbol(value) {
|
||||
let crypto_symbol = value;
|
||||
@@ -3316,7 +3597,6 @@ function removeStockPorftolio() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// update stock portfolio position with new values
|
||||
function updateStockPorftolio() {
|
||||
|
||||
@@ -3381,6 +3661,102 @@ function updateStockPorftolio() {
|
||||
}
|
||||
|
||||
|
||||
// remove global stock portfolio position
|
||||
function removeGlobalStockPorftolio() {
|
||||
|
||||
let remove_globalstock_symbol = document.getElementById('globalstocks_symbol').value;
|
||||
|
||||
if (remove_globalstock_symbol !== '') {
|
||||
document.getElementById('globalstocks_port_cost').value = '';
|
||||
document.getElementById('globalstocks_port_shares').value = '';
|
||||
document.getElementById('globalstocks_port_date').value = '';
|
||||
|
||||
fetch("/deleteGlobalPortfolioPosition", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(remove_globalstock_symbol),
|
||||
});
|
||||
|
||||
document.getElementById('globalstockremoved-p').innerHTML = 'Global stock Position Removed!';
|
||||
document.getElementById('removed-globalstock-p').style.display = "block";
|
||||
setTimeout(function hideElement() {
|
||||
document.getElementById('removed-globalstock-p').style.display = "none";
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
else {
|
||||
document.getElementById('globalstockremoved-p').innerHTML = 'No symbol selected.';
|
||||
document.getElementById('removed-globalstock-p').style.display = "block";
|
||||
setTimeout(function hideElement() {
|
||||
document.getElementById('removed-globalstock-p').style.display = "none";
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// update global stock portfolio position with new values
|
||||
function updateGlobalStockPorftolio() {
|
||||
|
||||
let update_globalstock_cost = document.getElementById('globalstocks_port_cost').value;
|
||||
let update_globalstock_shares = document.getElementById('globalstocks_port_shares').value;
|
||||
let update_globalsymbol = document.getElementById('globalstocks_symbol').value;
|
||||
let update_globalstock_days = document.getElementById('globalstocks_port_date').value;
|
||||
|
||||
let update_globalstock_settings = {
|
||||
shares:update_globalstock_shares,
|
||||
cost:update_globalstock_cost,
|
||||
symbol:update_globalsymbol,
|
||||
days:update_globalstock_days,
|
||||
};
|
||||
|
||||
if ((update_globalsymbol === '') || (update_globalsymbol === ' ')) {
|
||||
document.getElementById('globalstockremoved-p').innerHTML = 'No symbol selected.';
|
||||
document.getElementById('removed-globalstock-p').style.display = "block";
|
||||
setTimeout(function hideElement() {
|
||||
document.getElementById('removed-globalstock-p').style.display = "none";
|
||||
}, 5000);
|
||||
}
|
||||
else if ((update_globalstock_cost === ' ') || (update_globalstock_shares === ' ') || (update_globalstock_days === ' ')) {
|
||||
document.getElementById('globalstockremoved-p').innerHTML = 'No spaces.';
|
||||
document.getElementById('removed-globalstock-p').style.display = "block";
|
||||
setTimeout(function hideElement() {
|
||||
document.getElementById('removed-globalstock-p').style.display = "none";
|
||||
}, 5000);
|
||||
}
|
||||
else if ((isNaN(update_globalstock_cost)) || (isNaN(update_globalstock_shares))) {
|
||||
document.getElementById('globalstockremoved-p').innerHTML = 'No text characters, only numbers.';
|
||||
document.getElementById('removed-globalstock-p').style.display = "block";
|
||||
setTimeout(function hideElement() {
|
||||
document.getElementById('removed-globalstock-p').style.display = "none";
|
||||
}, 5000);
|
||||
}
|
||||
else if ((!update_globalstock_days.includes('-')) && (update_globalstock_days !== '')) {
|
||||
document.getElementById('globalstockremoved-p').innerHTML = 'Incorrect date format, it should be YYYY-MM-DD';
|
||||
document.getElementById('removed-globalstock-p').style.display = "block";
|
||||
setTimeout(function hideElement() {
|
||||
document.getElementById('removed-globalstock-p').style.display = "none";
|
||||
}, 5000);
|
||||
}
|
||||
else if (((update_globalstock_shares !== '') || (update_globalstock_cost !== '') || (update_globalstock_days !== '')) && ((update_globalstock_shares === '') || (update_globalstock_cost === '') || (update_globalstock_days === ''))) {
|
||||
document.getElementById('globalstockremoved-p').innerHTML = 'Some fields are empty.';
|
||||
document.getElementById('removed-globalstock-p').style.display = "block";
|
||||
setTimeout(function hideElement() {
|
||||
document.getElementById('removed-globalstock-p').style.display = "none";
|
||||
}, 5000);
|
||||
}
|
||||
else {
|
||||
fetch("/saveGlobalPortfolioSettings", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(update_globalstock_settings),
|
||||
});
|
||||
|
||||
document.getElementById('updated-globalstock-p').style.display = "block";
|
||||
setTimeout(function hideElement() {
|
||||
document.getElementById('updated-globalstock-p').style.display = "none";
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// remove crypto portfolio position
|
||||
function removeCryptoPorftolio() {
|
||||
|
||||
@@ -3568,7 +3944,7 @@ function featureSavePrompt() {
|
||||
|
||||
|
||||
const pageIDs = ['Page1', 'Page2', 'Page3', 'Page4', 'Page5', 'Page6', 'Page7', 'Page8', 'Page9', 'Page10', 'Page11', 'Page12', 'Page13',
|
||||
'Page14', 'Page15', 'Page16', 'Page17', 'Page18', 'Page19', 'Page20', 'Page21', 'Page22', 'Page23', 'Page24', 'Page25'];
|
||||
'Page14', 'Page15', 'Page16', 'Page17', 'Page18', 'Page19', 'Page20', 'Page21', 'Page22', 'Page23', 'Page24', 'Page25', 'Page26', 'Page27'];
|
||||
|
||||
for (const pageID of pageIDs) {
|
||||
// Select the parent div
|
||||
@@ -3694,6 +4070,27 @@ function uploadStockLogo() {
|
||||
}
|
||||
}
|
||||
|
||||
// UPLOAD CUSTOM GLOBAL STOCK LOGO
|
||||
function uploadGlobalStockLogo() {
|
||||
const fileInput_globalstocks = document.getElementById("globalstocks-logo-upload-browse");
|
||||
if (fileInput_globalstocks.value !== "") {
|
||||
const globalstock_file = fileInput_globalstocks.files[0];
|
||||
const globalstock_upload_msg = document.getElementById("globalstocklogoupload");
|
||||
|
||||
const formData_globalstocks = new FormData();
|
||||
formData_globalstocks.append('file', globalstock_file)
|
||||
fetch('/upload_globalstocks', {
|
||||
method: 'POST',
|
||||
body: formData_globalstocks
|
||||
})
|
||||
globalstock_upload_msg.style.display = "block";
|
||||
setTimeout(function hideElement() {
|
||||
globalstock_upload_msg.style.display = "none";
|
||||
}, 5000);
|
||||
fileInput_globalstocks.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
// UPLOAD CUSTOM CRYPTO LOGO
|
||||
function uploadCryptoLogo() {
|
||||
const fileInput_crypto = document.getElementById("crypto-logo-upload-browse");
|
||||
|
@@ -1136,6 +1136,10 @@ input[type=checkbox]:hover {
|
||||
#demo {
|
||||
color:red;
|
||||
}
|
||||
#demo10 {
|
||||
color:red;
|
||||
}
|
||||
|
||||
|
||||
#demo2 {
|
||||
color:red;
|
||||
@@ -1172,7 +1176,9 @@ input[type=checkbox]:hover {
|
||||
#demo-portfolio {
|
||||
color:red;
|
||||
}
|
||||
|
||||
#demo-portfolio-globalstocks {
|
||||
color:red;
|
||||
}
|
||||
#demo-portfolio-crypto {
|
||||
color:red;
|
||||
}
|
||||
|
520
stockTicker.py
@@ -107,24 +107,24 @@ class StockTicker():
|
||||
#sys.exit()
|
||||
self.points = True # display crypto change in points or percent
|
||||
|
||||
self.functions = {'Stocks': self.getStockImage, 'Crypto': self.getCryptoImage, 'Forex': self.getForexImage, 'Sector Performance': self.getSectorImage,
|
||||
self.functions = {'Stocks': self.getStockImage, 'Global Stocks': self.getGlobalStockImage, 'Crypto': self.getCryptoImage, 'Forex': self.getForexImage, 'Sector Performance': self.getSectorImage, 'Inspirational Quotes': self.getQuotesImage,
|
||||
'Daily Forecast':self.getDailyWeatherImage, 'Current Weather': self.getTodayWeatherImage, 'Jokes': self.getJokesImage, 'Place (Reddit)': self.getPlaceImage,
|
||||
'Sports (Team Stats)':lambda : self.getLeagueTableImage('premier_league'), 'Sports (Past Games)': lambda:self.getLeagueImage('NBA', 'past'),
|
||||
'Sports (Upcoming Games)': lambda : self.getLeagueImage('NHL', 'future'), 'Sports (Live Games)': lambda: self.getLeagueImage('NBA', 'live'),
|
||||
'News':self.getNewsImage, 'Custom Messages': self.getUserMessages, 'Commodities': self.getCommoditiesImage, 'Indices': self.getIndicesImage, 'Movies': self.getMoviesImage, 'Gainers, Losers, Active': self.getMarketImage,
|
||||
'Economic Calendar': self.getEconomicImage, 'IPO Calendar':self.getIpoImage, 'IPO Calendar Prof':self.getIpoProfessional, 'Economic Calendar Prof': self.getEconomicProfessional, 'Gainers, Losers, Active Prof': self.getMarketProfessional,
|
||||
|
||||
'Stocks Prof': self.getStockProfessional, 'Crypto Prof': self.getCryptoProfessional, 'Forex Prof': self.getForexProfessional, 'Jokes Prof': self.getJokesProfessional, 'Place (Reddit) Prof': self.getPlaceImageProfessional,
|
||||
'Stocks Prof': self.getStockProfessional, 'Global Stocks Prof': self.getGlobalStockProfessional, 'Crypto Prof': self.getCryptoProfessional, 'Forex Prof': self.getForexProfessional, 'Jokes Prof': self.getJokesProfessional, 'Place (Reddit) Prof': self.getPlaceImageProfessional, 'Inspirational Quotes Prof': self.getQuotesProfessional,
|
||||
'Current Weather Prof': self.getTodayWeatherProfessional, 'News Prof':self.getNewsProfessional, 'Commodities Prof':self.getCommoditiesProfessional, 'Indices Prof': self.getIndicesProfessional, 'Sector Performance Prof': self.getSectorProfessional,
|
||||
'Daily Forecast Prof':self.getDailyWeatherProfessional, 'Sports (Team Stats) Prof':lambda : self.getLeagueTableProfessional('NHL'), 'Sports (Upcoming Games) Prof': lambda : self.getLeagueProfessional('NHL', 'future'),
|
||||
'Sports (Past Games) Prof': lambda : self.getLeagueProfessional('NBA', 'past'), 'Custom Messages Prof': self.getUserMessagesProfessional, 'Custom Images Prof': self.getUserImagesProfessional, 'Movies Prof': self.getMoviesProfessional, 'Sports (Live Games) Prof': lambda : self.getLeagueProfessional('NBA', 'live')}
|
||||
|
||||
self.JSONs = {'Stocks': 'csv/stocks_settings.json', 'Crypto': 'csv/crypto_settings.json', 'Forex': 'csv/forex_settings.json', 'Jokes': 'csv/jokes_settings.json',
|
||||
self.JSONs = {'Stocks': 'csv/stocks_settings.json', 'Global Stocks': 'csv/globalstocks_settings.json', 'Crypto': 'csv/crypto_settings.json', 'Forex': 'csv/forex_settings.json', 'Jokes': 'csv/jokes_settings.json', 'Inspirational Quotes': 'csv/quotes_settings.json',
|
||||
'Daily Forecast':'csv/daily_weather.json', 'Current Weather': 'csv/current_weather.json', 'Commodities':'csv/commodities_settings.json', 'Indices': 'csv/indices_settings.json',
|
||||
'Sports (Team Stats)': 'csv/league_tables.json', 'Sports (Past Games)': 'csv/past_games.json', 'IPO Calendar': 'csv/ipo_settings.json', 'Economic Calendar': 'csv/economic_settings.json',
|
||||
'Sports (Upcoming Games)': 'csv/upcoming_games.json', 'Sports (Live Games)': 'csv/live_games.json', 'Movies': 'csv/movie_settings.json', 'Clock 1': 'csv/clock1_settings.json', 'Clock 2': 'csv/clock2_settings.json', 'World Clock': 'csv/worldclock_settings.json',
|
||||
'News':'csv/news_settings.json', 'Custom Images': 'csv/image_settings.json', 'Custom GIFs': 'csv/GIF_settings.json', 'Custom Messages': 'csv/message_settings.json', 'Clock 1 Prof': 'csv/clock1_settings.json', 'World Clock Prof': 'csv/worldclock_settings.json',
|
||||
'Stocks Prof': 'csv/stocks_settings.json', 'Crypto Prof': 'csv/crypto_settings.json', 'Forex Prof': 'csv/forex_settings.json', 'Jokes Prof': 'csv/jokes_settings.json', 'Clock 2 Prof': 'csv/clock2_settings.json',
|
||||
'Stocks Prof': 'csv/stocks_settings.json', 'Global Stocks Prof': 'csv/globalstocks_settings.json', 'Crypto Prof': 'csv/crypto_settings.json', 'Forex Prof': 'csv/forex_settings.json', 'Jokes Prof': 'csv/jokes_settings.json', 'Clock 2 Prof': 'csv/clock2_settings.json',
|
||||
'Current Weather Prof': 'csv/current_weather.json', 'News Prof':'csv/news_settings.json', 'Commodities Prof':'csv/commodities_settings.json', 'Indices Prof': 'csv/indices_settings.json',
|
||||
'Daily Forecast Prof':'csv/daily_weather.json', 'Sports (Team Stats) Prof': 'csv/league_tables.json', 'Sports (Upcoming Games) Prof': 'csv/upcoming_games.json', 'Sports (Past Games) Prof': 'csv/past_games.json', 'Custom Messages Prof': 'csv/message_settings.json', 'Custom Images Prof': 'csv/image_settings.json', 'Movies Prof': 'csv/movie_settings.json', 'Sports (Live Games) Prof': 'csv/live_games.json', 'IPO Calendar Prof': 'csv/ipo_settings.json', 'Economic Calendar Prof': 'csv/economic_settings.json',
|
||||
'Gainers, Losers, Active':'csv/market_settings.json', 'Gainers, Losers, Active Prof':'csv/market_settings.json', 'Sector Performance':'csv/sector_settings.json', 'Sector Performance Prof':'csv/sector_settings.json', 'Place (Reddit)':'csv/place_settings.json', 'Place (Reddit) Prof':'csv/place_settings.json'}
|
||||
@@ -3694,7 +3694,424 @@ class StockTicker():
|
||||
finalDisplayImage = self.stitchImage(image_list)
|
||||
self.blank = Image.new('RGB', (10, 32))
|
||||
return finalDisplayImage
|
||||
|
||||
|
||||
def getGlobalStockImage(self):
|
||||
|
||||
f = open('csv/globalstocks_settings.json', 'r')
|
||||
all_globalstocks_settings = json.load(f)
|
||||
f.close()
|
||||
if all_globalstocks_settings['title']:
|
||||
title_img = self.openImage('feature_titles/globalstocks.png')
|
||||
image_list = [title_img]
|
||||
image_list.append(self.blank)
|
||||
else:
|
||||
image_list = []
|
||||
if all_globalstocks_settings['chart']:
|
||||
try:
|
||||
f = open('csv/portfolio_global_settings.json', 'r')
|
||||
portfolio_settings = json.load(f)['symbols']
|
||||
f.close()
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
if all_globalstocks_settings['display_name']:
|
||||
names = True
|
||||
else:
|
||||
names = False
|
||||
except:
|
||||
names = False
|
||||
pass
|
||||
|
||||
stock_info = all_globalstocks_settings['symbols']
|
||||
symbols = list(stock_info.keys())
|
||||
|
||||
for i, symbol in enumerate(symbols):
|
||||
try:
|
||||
info = stock_info[symbol]
|
||||
|
||||
change = float(info['change']) #TEXT
|
||||
if names:
|
||||
try:
|
||||
ticker = info['name'].upper() #TEXT
|
||||
except:
|
||||
ticker = symbol
|
||||
else:
|
||||
ticker = symbol
|
||||
|
||||
arrow, change = self.getArrow(change)
|
||||
|
||||
percent_change = '%.2f' % abs(float(info['percent_change'])) + '%'
|
||||
point_change = '%.2f' % abs(change)
|
||||
|
||||
current = '%.2f' % float(info['current']) #TEXT
|
||||
|
||||
if not all_globalstocks_settings['percent']:
|
||||
percent_change = False
|
||||
if not all_globalstocks_settings['point']:
|
||||
point_change = False
|
||||
|
||||
midFrame = self.textToImage(ticker, current, arrow, percent_change, point_change) #IMAGE THE TEXT
|
||||
|
||||
if all_globalstocks_settings['logos']:
|
||||
try:
|
||||
ticker = symbol
|
||||
logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'global_stocks')
|
||||
logo = self.openImage(os.path.join(logos_path, ticker + '.png'))
|
||||
stitchedStock = self.stitchImage([logo,midFrame])
|
||||
except Exception as e:
|
||||
stitchedStock = midFrame
|
||||
else:
|
||||
stitchedStock = midFrame
|
||||
|
||||
try:
|
||||
if all_globalstocks_settings['lohivol']:
|
||||
font = ImageFont.load("./fonts/5x8.pil")
|
||||
try:
|
||||
day_low = '%.2f' % float(info['day_low'])
|
||||
day_high = '%.2f' % float(info['day_high'])
|
||||
volume = info['volume']
|
||||
|
||||
daylow_img = self.textImage(day_low, font, r=0, g=255, b=0)
|
||||
daylow_t_img = self.textImage('Lo', font, r=255, g=255, b=255)
|
||||
dayhi_img = self.textImage(day_high, font, r=0,g=255,b=0)
|
||||
dayhi_t_img = self.textImage('Hi', font, r=255,g=255,b=255)
|
||||
vol_img = self.textImage(volume, font, r=0,g=255,b=0)
|
||||
vol_t_img = self.textImage('Vol', font, r=255,g=255,b=255)
|
||||
lohivol_img = Image.new('RGB', (max(daylow_img.size[0] + daylow_t_img.size[0], dayhi_img.size[0] + dayhi_t_img.size[0],
|
||||
vol_img.size[0] + vol_t_img.size[0]) + 5, 32))
|
||||
lohivol_img.paste(daylow_t_img, (0, 3))
|
||||
lohivol_img.paste(daylow_img, (daylow_t_img.size[0],3))
|
||||
lohivol_img.paste(dayhi_t_img, (0, 12))
|
||||
lohivol_img.paste(dayhi_img, (dayhi_t_img.size[0], 12))
|
||||
lohivol_img.paste(vol_t_img, (0, 21))
|
||||
lohivol_img.paste(vol_img, (vol_t_img.size[0], 21))
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
if all_globalstocks_settings['chart'] and (symbol in portfolio_settings): #IF USER INPUTTED PORTFOLIO SETTINGS, DISPLAY PORTFOLIO INFO
|
||||
try:
|
||||
cost = portfolio_settings[symbol]['cost']
|
||||
day = portfolio_settings[symbol]['day']
|
||||
day_start = datetime.strptime(str(day), "%Y-%m-%d")
|
||||
day_today = datetime.strptime(datetime.now(pytz.utc).strftime("%Y-%m-%d"), "%Y-%m-%d")
|
||||
day = str((day_today - day_start).days)
|
||||
shares = portfolio_settings[symbol]['shares']
|
||||
|
||||
original_value = float(cost) * float(shares)
|
||||
new_value = float(info['current']) * float(shares)
|
||||
value_day_change_percent = ((float(info['percent_change'])/100) * new_value)
|
||||
|
||||
font = ImageFont.load("./fonts/5x8.pil")
|
||||
cost_img = self.textImage('Cost', font, r = 255, g = 255 , b = 255)
|
||||
cost2_img = self.textImage(cost, font, r = 0, g = 255, b = 0)
|
||||
shares_img = self.textImage('Shares', font, r = 255, g = 255 , b = 255)
|
||||
shares2_img = self.textImage(shares, font, r = 0, g = 255, b = 0)
|
||||
|
||||
pnlchange = new_value - original_value
|
||||
pnlpercent = ((new_value - original_value) / original_value) * 100
|
||||
|
||||
pnlpercent_img = self.textImage('P/L%', font, r = 255, g = 255 , b = 255)
|
||||
if pnlpercent >= 0:
|
||||
pnlpercent2_img = self.textImage(str('%.2f' % abs(pnlpercent)) + '%', font, r = 0, g = 255, b = 0)
|
||||
else:
|
||||
pnlpercent2_img = self.textImage(str('%.2f' % abs(pnlpercent)) + '%', font, r = 255, g = 0, b = 0)
|
||||
|
||||
daypercent_img = self.textImage('Day%', font, r = 255, g = 255 , b = 255)
|
||||
if float(info['percent_change']) >= 0:
|
||||
daypercent2_img = self.textImage(str('%.2f' % abs(float(info['percent_change']))) +'%', font, r = 0, g = 255, b = 0)
|
||||
else:
|
||||
daypercent2_img = self.textImage(str('%.2f' % abs(float(info['percent_change'])))+'%', font, r = 255, g = 0, b = 0)
|
||||
|
||||
days_img = self.textImage('Days', font, r = 255, g = 255 , b = 255)
|
||||
days2_img = self.textImage(day, font, r = 0, g = 255, b = 0)
|
||||
value_img = self.textImage('Value', font, r = 255, g = 255 , b = 255)
|
||||
value2_img = self.textImage(str('%.2f' % abs(original_value)), font, r = 0, g = 255, b = 0)
|
||||
|
||||
pnlchange_img = self.textImage('P/L$', font, r = 255, g = 255 , b = 255)
|
||||
if pnlchange >= 0:
|
||||
pnlchange2_img = self.textImage(str('%.2f' % abs(pnlchange)), font, r = 0, g = 255, b = 0)
|
||||
else:
|
||||
pnlchange2_img = self.textImage(str('%.2f' % abs(pnlchange)), font, r = 255, g = 0, b = 0)
|
||||
|
||||
daychange_img = self.textImage('Day$', font, r = 255, g = 255 , b = 255)
|
||||
if value_day_change_percent >= 0:
|
||||
daychange2_img = self.textImage(str('%.2f' % abs(value_day_change_percent)), font, r = 0, g = 255, b = 0)
|
||||
else:
|
||||
daychange2_img = self.textImage(str('%.2f' % abs(value_day_change_percent)), font, r = 255, g = 0, b = 0)
|
||||
|
||||
x_offset = 0
|
||||
|
||||
img = Image.new('RGB', (max(cost_img.size[0], cost2_img.size[0], days_img.size[0], days2_img.size[0]) + 7 +
|
||||
max(shares_img.size[0], shares2_img.size[0], value2_img.size[0], value_img.size[0]) + 7 +
|
||||
max(pnlpercent_img.size[0], pnlpercent2_img.size[0], pnlchange_img.size[0], pnlchange2_img.size[0]) + 7 +
|
||||
max(daypercent_img.size[0], daypercent2_img.size[0], daychange_img.size[0], daychange2_img.size[0]) + 15, 32))
|
||||
|
||||
img.paste(cost_img, (x_offset, 0))
|
||||
img.paste(cost2_img, (x_offset, 8))
|
||||
img.paste(days_img, (x_offset, 16))
|
||||
img.paste(days2_img, (x_offset, 24))
|
||||
x_offset += max(cost_img.size[0], cost2_img.size[0], days_img.size[0], days2_img.size[0]) + 7
|
||||
|
||||
img.paste(shares_img, (x_offset, 0))
|
||||
img.paste(shares2_img, (x_offset, 8))
|
||||
img.paste(value_img, (x_offset, 16))
|
||||
img.paste(value2_img, (x_offset, 24))
|
||||
x_offset += max(shares_img.size[0], shares2_img.size[0], value2_img.size[0], value_img.size[0]) + 7
|
||||
|
||||
img.paste(pnlpercent_img, (x_offset, 0))
|
||||
img.paste(pnlpercent2_img, (x_offset, 8))
|
||||
img.paste(pnlchange_img, (x_offset, 16))
|
||||
img.paste(pnlchange2_img, (x_offset, 24))
|
||||
x_offset += max(pnlpercent_img.size[0], pnlpercent2_img.size[0], pnlchange_img.size[0], pnlchange2_img.size[0]) + 7
|
||||
|
||||
img.paste(daypercent_img, (x_offset, 0))
|
||||
img.paste(daypercent2_img, (x_offset, 8))
|
||||
img.paste(daychange_img, (x_offset,16))
|
||||
img.paste(daychange2_img, (x_offset, 24))
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
|
||||
image_list.append(stitchedStock)
|
||||
try:
|
||||
if all_globalstocks_settings['lohivol']:
|
||||
try:
|
||||
image_list.append(lohivol_img)
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
if all_globalstocks_settings['chart'] and (symbol in portfolio_settings):
|
||||
try:
|
||||
image_list.append(img)
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
image_list.append(self.blank)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
finalDisplayImage = self.stitchImage(image_list)
|
||||
|
||||
return finalDisplayImage
|
||||
|
||||
|
||||
def getGlobalStockProfessional(self):
|
||||
self.blank = Image.new('RGB', (0, 16))
|
||||
|
||||
f = open('csv/globalstocks_settings.json', 'r')
|
||||
all_stocks_settings = json.load(f)
|
||||
f.close()
|
||||
|
||||
if all_stocks_settings['title']:
|
||||
title_img = self.openImage('feature_titles/small_feature_titles/globalstocks.png')
|
||||
image_list = [title_img, Image.new('RGB', (5, 16))]
|
||||
image_list.append(self.blank)
|
||||
else:
|
||||
image_list = []
|
||||
|
||||
if all_stocks_settings['chart']:
|
||||
try:
|
||||
f = open('csv/portfolio_global_settings.json', 'r')
|
||||
portfolio_settings = json.load(f)['symbols']
|
||||
f.close()
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
if all_stocks_settings['display_name']:
|
||||
names = True
|
||||
else:
|
||||
names = False
|
||||
except:
|
||||
names = False
|
||||
pass
|
||||
stock_info = all_stocks_settings['symbols']
|
||||
symbols = list(stock_info.keys())
|
||||
|
||||
for i, symbol in enumerate(symbols):
|
||||
|
||||
try:
|
||||
info = stock_info[symbol]
|
||||
|
||||
change = float(info['change'])#TEXT
|
||||
if names:
|
||||
try:
|
||||
ticker = info['name'].upper() + 'display_name' #TEXT
|
||||
except:
|
||||
ticker = symbol
|
||||
else:
|
||||
ticker = symbol
|
||||
arrow, change = self.getArrow(change, professional=True)
|
||||
|
||||
if all_stocks_settings["percent"]:
|
||||
change = '%.2f' % abs(float(info['percent_change'])) + '%'
|
||||
else:
|
||||
change = '%.2f' % abs(change)
|
||||
|
||||
current = '%.2f' % float(info['current']) #TEXT
|
||||
midFrame = self.textToImageProf(ticker, current, change, arrow, font=ImageFont.load("./fonts/6x10.pil")) #IMAGE THE TEXT
|
||||
|
||||
if all_stocks_settings['logos']:
|
||||
ticker = symbol
|
||||
try:
|
||||
logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'global_stocks')
|
||||
logo = Image.open(os.path.join(logos_path, ticker + '.png'))
|
||||
# half the size of the logo
|
||||
width, height = logo.size
|
||||
logo = logo.resize((int(width/2), int(height/2)))
|
||||
stitchedStock = self.stitchImage([logo,midFrame])
|
||||
except Exception as e:
|
||||
stitchedStock = midFrame
|
||||
else:
|
||||
stitchedStock = midFrame
|
||||
try:
|
||||
if all_stocks_settings['lohivol']:
|
||||
font = ImageFont.load("./fonts/4x6.pil")
|
||||
try:
|
||||
day_low = '%.2f' % float(info['day_low'])
|
||||
day_high = '%.2f' % float(info['day_high'])
|
||||
volume = info['volume']
|
||||
|
||||
daylow_img = self.textImage(day_low, font, r=0, g=255, b=0)
|
||||
daylow_t_img = self.textImage('Lo', font, r=255, g=255, b=255)
|
||||
dayhi_img = self.textImage(day_high, font, r=0,g=255,b=0)
|
||||
dayhi_t_img = self.textImage('Hi', font, r=255,g=255,b=255)
|
||||
vol_img = self.textImage(volume, font, r=0,g=255,b=0)
|
||||
vol_t_img = self.textImage('Vol', font, r=255,g=255,b=255)
|
||||
lohivol_img = Image.new('RGB', (max(daylow_t_img.size[0] + daylow_img.size[0], dayhi_t_img.size[0] + dayhi_img.size[0]) + 2+vol_t_img.size[0] + vol_img.size[0] + 8, 16))
|
||||
lohivol_img.paste(daylow_t_img, (0, 3))
|
||||
lohivol_img.paste(daylow_img, (daylow_t_img.size[0],3))
|
||||
lohivol_img.paste(dayhi_t_img, (0, 9))
|
||||
lohivol_img.paste(dayhi_img, (dayhi_t_img.size[0], 9))
|
||||
lohivol_img.paste(vol_t_img, (max(daylow_t_img.size[0] + daylow_img.size[0], dayhi_t_img.size[0] + dayhi_img.size[0])+2, 3))
|
||||
lohivol_img.paste(vol_img, (max(daylow_t_img.size[0] + daylow_img.size[0], dayhi_t_img.size[0] + dayhi_img.size[0]) + 2+vol_t_img.size[0], 3))
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
if all_stocks_settings['chart'] and (symbol in portfolio_settings): #IF USER INPUTTED PORTFOLIO SETTINGS, DISPLAY PORTFOLIO INFO
|
||||
try:
|
||||
cost = portfolio_settings[symbol]['cost']
|
||||
day = portfolio_settings[symbol]['day']
|
||||
day_start = datetime.strptime(str(day), "%Y-%m-%d")
|
||||
day_today = datetime.strptime(datetime.now(pytz.utc).strftime("%Y-%m-%d"), "%Y-%m-%d")
|
||||
day = str((day_today - day_start).days)
|
||||
shares = portfolio_settings[symbol]['shares']
|
||||
|
||||
original_value = float(cost) * float(shares)
|
||||
new_value = float(info['current']) * float(shares)
|
||||
value_day_change_percent = ((float(info['percent_change'])/100) * new_value)
|
||||
|
||||
font = ImageFont.load("./fonts/5x8.pil")
|
||||
cost_img = self.textImage('Cost', font, r = 255, g = 255 , b = 255)
|
||||
cost2_img = self.textImage(cost, font, r = 0, g = 255, b = 0)
|
||||
shares_img = self.textImage('Shares', font, r = 255, g = 255 , b = 255)
|
||||
shares2_img = self.textImage(shares, font, r = 0, g = 255, b = 0)
|
||||
|
||||
pnlchange = new_value - original_value
|
||||
pnlpercent = ((new_value - original_value) / original_value) * 100
|
||||
|
||||
pnlpercent_img = self.textImage('P/L%', font, r = 255, g = 255 , b = 255)
|
||||
if pnlpercent >= 0:
|
||||
pnlpercent2_img = self.textImage(str('%.2f' % abs(pnlpercent)) + '%', font, r = 0, g = 255, b = 0)
|
||||
else:
|
||||
pnlpercent2_img = self.textImage(str('%.2f' % abs(pnlpercent)) + '%', font, r = 255, g = 0, b = 0)
|
||||
|
||||
|
||||
daypercent_img = self.textImage('Day%', font, r = 255, g = 255 , b = 255)
|
||||
if float(info['percent_change']) >= 0:
|
||||
daypercent2_img = self.textImage(str('%.2f' % abs(float(info['percent_change']))) +'%', font, r = 0, g = 255, b = 0)
|
||||
else:
|
||||
daypercent2_img = self.textImage(str('%.2f' % abs(float(info['percent_change'])))+'%', font, r = 255, g = 0, b = 0)
|
||||
|
||||
days_img = self.textImage('Days', font, r = 255, g = 255 , b = 255)
|
||||
days2_img = self.textImage(day, font, r = 0, g = 255, b = 0)
|
||||
value_img = self.textImage('Value', font, r = 255, g = 255 , b = 255)
|
||||
value2_img = self.textImage(str('%.2f' % abs(original_value)), font, r = 0, g = 255, b = 0)
|
||||
|
||||
pnlchange_img = self.textImage('P/L$', font, r = 255, g = 255 , b = 255)
|
||||
if pnlchange >= 0:
|
||||
pnlchange2_img = self.textImage(str('%.2f' % abs(pnlchange)), font, r = 0, g = 255, b = 0)
|
||||
else:
|
||||
pnlchange2_img = self.textImage(str('%.2f' % abs(pnlchange)), font, r = 255, g = 0, b = 0)
|
||||
|
||||
daychange_img = self.textImage('Day$', font, r = 255, g = 255 , b = 255)
|
||||
if value_day_change_percent >= 0:
|
||||
daychange2_img = self.textImage(str('%.2f' % abs(value_day_change_percent)), font, r = 0, g = 255, b = 0)
|
||||
else:
|
||||
daychange2_img = self.textImage(str('%.2f' % abs(value_day_change_percent)), font, r = 255, g = 0, b = 0)
|
||||
|
||||
x_offset = 0
|
||||
|
||||
img = Image.new('RGB', (max(cost_img.size[0], cost2_img.size[0]) + 5 + max(days_img.size[0], days2_img.size[0]) + 5 +
|
||||
max(shares_img.size[0], shares2_img.size[0]) + 5 + max(value2_img.size[0], value_img.size[0]) + 5 +
|
||||
max(pnlpercent_img.size[0], pnlpercent2_img.size[0]) + 5 + max(pnlchange_img.size[0], pnlchange2_img.size[0]) + 5 +
|
||||
max(daypercent_img.size[0], daypercent2_img.size[0]) + 5 + max(daychange_img.size[0], daychange2_img.size[0]) + 10,16))
|
||||
|
||||
img.paste(cost_img, (x_offset, 1))
|
||||
img.paste(cost2_img, (x_offset, 9))
|
||||
x_offset += max(cost_img.size[0], cost2_img.size[0]) + 4
|
||||
img.paste(days_img, (x_offset, 1))
|
||||
img.paste(days2_img, (x_offset, 9))
|
||||
x_offset += max(days_img.size[0], days2_img.size[0]) + 4
|
||||
|
||||
img.paste(shares_img, (x_offset, 1))
|
||||
img.paste(shares2_img, (x_offset, 9))
|
||||
x_offset += max(shares_img.size[0], shares2_img.size[0]) + 4
|
||||
img.paste(value_img, (x_offset, 1))
|
||||
img.paste(value2_img, (x_offset, 9))
|
||||
x_offset += max(value2_img.size[0], value_img.size[0]) + 4
|
||||
|
||||
img.paste(pnlpercent_img, (x_offset, 1))
|
||||
img.paste(pnlpercent2_img, (x_offset, 9))
|
||||
x_offset += max(pnlpercent_img.size[0], pnlpercent2_img.size[0]) + 4
|
||||
img.paste(pnlchange_img, (x_offset, 1))
|
||||
img.paste(pnlchange2_img, (x_offset, 9))
|
||||
x_offset += max(pnlchange_img.size[0], pnlchange2_img.size[0]) + 4
|
||||
|
||||
img.paste(daypercent_img, (x_offset, 1))
|
||||
img.paste(daypercent2_img, (x_offset, 9))
|
||||
x_offset += max(daypercent_img.size[0], daypercent2_img.size[0]) + 4
|
||||
img.paste(daychange_img, (x_offset,1))
|
||||
img.paste(daychange2_img, (x_offset, 9))
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
|
||||
image_list.append(stitchedStock)
|
||||
try:
|
||||
if all_stocks_settings['lohivol']:
|
||||
try:
|
||||
image_list.append(lohivol_img)
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
if all_stocks_settings['chart'] and (symbol in portfolio_settings):
|
||||
try:
|
||||
image_list.append(img)
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
|
||||
image_list.append(self.blank)
|
||||
|
||||
except Exception as e:
|
||||
pass
|
||||
finalDisplayImage = self.stitchImage(image_list)
|
||||
self.blank = Image.new('RGB', (10, 32))
|
||||
return finalDisplayImage
|
||||
|
||||
|
||||
def getNewsImage(self):
|
||||
|
||||
@@ -7729,6 +8146,89 @@ class StockTicker():
|
||||
return self.stitchImage(image_list)
|
||||
|
||||
|
||||
def getQuotesImage(self):
|
||||
|
||||
f = open('csv/quotes_settings.json', 'r')
|
||||
quotes_settings = json.load(f)
|
||||
f.close()
|
||||
|
||||
if quotes_settings['title']:
|
||||
title_img = self.openImage('feature_titles/quotes.png')
|
||||
image_list = [title_img]
|
||||
else:
|
||||
image_list = []
|
||||
font = ImageFont.load("./fonts/8x13B.pil")
|
||||
font2 = ImageFont.load("./fonts/6x10.pil")
|
||||
sun_img = self.openImage('logos/sun_quote.png')
|
||||
try:
|
||||
for index, each in enumerate(quotes_settings['quotes']):
|
||||
if index == 0:
|
||||
quote_img = self.textImage(each['quote'], font, 248, 152, 128)
|
||||
author_img = self.textImage(each['author'], font2, 64, 181, 173)
|
||||
img = Image.new('RGB', (max(quote_img.size[0], author_img.size[0]) + 20,32))
|
||||
img.paste(quote_img, (0,7))
|
||||
img.paste(author_img, ((quote_img.size[0] - author_img.size[0] - 5), 21))
|
||||
image_list.append(img)
|
||||
else:
|
||||
quote_img = self.textImage(each['quote'], font, 248, 152, 128)
|
||||
author_img = self.textImage(each['author'], font2, 64, 181, 173)
|
||||
img = Image.new('RGB', (sun_img.size[0] + 5+ max(quote_img.size[0], author_img.size[0]) + 20,32))
|
||||
img.paste(sun_img, (0, 0))
|
||||
img.paste(quote_img, (sun_img.size[0] + 5,7))
|
||||
img.paste(author_img, (sun_img.size[0] + 5+(quote_img.size[0] - author_img.size[0] - 5), 21))
|
||||
image_list.append(img)
|
||||
except:
|
||||
img = Image.new('RGB',(180,32))
|
||||
no_quotes = self.textImage('No quotes available.', font, 255, 255, 255)
|
||||
img.paste(no_quotes,(0,7))
|
||||
image_list.append(img)
|
||||
pass
|
||||
|
||||
return self.stitchImage(image_list)
|
||||
|
||||
|
||||
def getQuotesProfessional(self):
|
||||
|
||||
f = open('csv/quotes_settings.json', 'r')
|
||||
quotes_settings = json.load(f)
|
||||
f.close()
|
||||
|
||||
if quotes_settings['title']:
|
||||
title_img = self.openImage('feature_titles/small_feature_titles/quotes.png')
|
||||
image_list = [title_img]
|
||||
else:
|
||||
image_list = []
|
||||
font = ImageFont.load("./fonts/5x8.pil")
|
||||
font2 = ImageFont.load("./fonts/4x6.pil")
|
||||
sun_img = self.openImage('logos/sun_quote_small.png')
|
||||
|
||||
try:
|
||||
for index, each in enumerate(quotes_settings['quotes']):
|
||||
if index == 0:
|
||||
quote_img = self.textImage(each['quote'], font, 248, 152, 128)
|
||||
author_img = self.textImage(each['author'], font2, 64, 181, 173)
|
||||
img = Image.new('RGB', (max(quote_img.size[0], author_img.size[0]) + 15,16))
|
||||
img.paste(quote_img, (0,0))
|
||||
img.paste(author_img, ((quote_img.size[0] - author_img.size[0] - 5), 10))
|
||||
image_list.append(img)
|
||||
else:
|
||||
quote_img = self.textImage(each['quote'], font, 248, 152, 128)
|
||||
author_img = self.textImage(each['author'], font2, 64, 181, 173)
|
||||
img = Image.new('RGB', (sun_img.size[0] + 5+ max(quote_img.size[0], author_img.size[0]) + 15,16))
|
||||
img.paste(sun_img, (0, 0))
|
||||
img.paste(quote_img, (sun_img.size[0] + 5,0))
|
||||
img.paste(author_img, (sun_img.size[0] + 5+(quote_img.size[0] - author_img.size[0] - 5), 10))
|
||||
image_list.append(img)
|
||||
except:
|
||||
img = Image.new('RGB',(180,16))
|
||||
no_quotes = self.textImage('No quotes available.', font, 255, 255, 255)
|
||||
img.paste(no_quotes,(0,0))
|
||||
image_list.append(img)
|
||||
pass
|
||||
|
||||
return self.stitchImage(image_list)
|
||||
|
||||
|
||||
def getMarketImage(self):
|
||||
f = open('csv/market_settings.json', 'r')
|
||||
market_settings = json.load(f)
|
||||
@@ -9764,6 +10264,8 @@ class StockTicker():
|
||||
market = self.getMarketProfessional()
|
||||
sector = self.getSectorProfessional()
|
||||
place = self.getPlaceImageProfessional()
|
||||
quotes = self.getQuotesProfessional()
|
||||
globalstocks = self.getGlobalStockProfessional()
|
||||
|
||||
x_offset = 0
|
||||
news.paste(weather, (x_offset, 16))
|
||||
@@ -9806,6 +10308,10 @@ class StockTicker():
|
||||
x_offset += sector.size[0]
|
||||
news.paste(place, (x_offset, 16))
|
||||
x_offset += place.size[0]
|
||||
news.paste(quotes, (x_offset, 16))
|
||||
x_offset += quotes.size[0]
|
||||
news.paste(globalstocks, (x_offset, 16))
|
||||
x_offset += globalstocks.size[0]
|
||||
self.double_buffer = self.matrix.CreateFrameCanvas()
|
||||
while True:
|
||||
kill = stock_ticker.scrollImage(news, offset_x = 128)
|
||||
@@ -9913,6 +10419,12 @@ class StockTicker():
|
||||
|
||||
elif msg == 'WCL':
|
||||
self.scrollFunctionsAnimated(['worldclock', 'worldclock'],animation = 'traditional')
|
||||
|
||||
elif msg == 'IQ':
|
||||
self.scrollFunctionsAnimated(['quotes', 'quotes'],animation = 'traditional')
|
||||
|
||||
elif msg == 'GS':
|
||||
self.scrollFunctionsAnimated(['globalstocks', 'globalstocks'],animation = 'traditional')
|
||||
|
||||
elif msg == 'A': #everything
|
||||
|
||||
|
@@ -39,7 +39,7 @@
|
||||
<!-- CSS Stylesheet linking -->
|
||||
|
||||
<!-- <link href="{{ url_for('static', filename='style.css') }}" type="text/css" rel="stylesheet" /> ALWAYS CHANGE VERSIONING WHENEVER CHANGES ARE MADE TO AVOID BAD CACHING -->
|
||||
<link rel="stylesheet" type="text/css" href="../static/style.css?ver=1.3.8"/>
|
||||
<link rel="stylesheet" type="text/css" href="../static/style.css?ver=1.3.9"/>
|
||||
|
||||
</head>
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<p class="text-white" id="version-text">Version 1.3.8</p>
|
||||
<p class="text-white" id="version-text">Version 1.3.9</p>
|
||||
<p class="text-white" id="version-text"><a href="https://docs.google.com/document/d/1TzvukZv_0Pd3TUM6Xe2wEkymn9uIT2qXUBFnMCQwp5g/edit?usp=sharing" target="_blank" id="footerlinks">Changelog</a></p>
|
||||
</nav>
|
||||
|
||||
@@ -2067,6 +2067,7 @@
|
||||
{%else%}
|
||||
|
||||
<li>Stocks</li>
|
||||
<li>Global Stocks</li>
|
||||
<li>Crypto</li>
|
||||
<li>Forex</li>
|
||||
<li>Commodities</li>
|
||||
@@ -2091,6 +2092,7 @@
|
||||
<li>Clock 1</li>
|
||||
<li>Clock 2</li>
|
||||
<li>World Clock</li>
|
||||
<li>Inspirational Quotes</li>
|
||||
|
||||
{%endif%}
|
||||
|
||||
@@ -2185,6 +2187,7 @@
|
||||
<div class="col-auto">
|
||||
<select id="drop" class="form-select">
|
||||
<option value="1">Stocks</option>
|
||||
<option value="27">Global Stocks</option>
|
||||
<option value="2">Crypto</option>
|
||||
<option value="3">Forex</option>
|
||||
<option value="14">Commodities</option>
|
||||
@@ -2209,6 +2212,7 @@
|
||||
<option value="23">Clock 1</option>
|
||||
<option value="24">Clock 2</option>
|
||||
<option value="25">World Clock</option>
|
||||
<option value="26">Inspirational Quotes</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -2217,13 +2221,9 @@
|
||||
<!-- Stocks -->
|
||||
|
||||
<div class="page" id="Page1">
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||
|
||||
<div class="row g-3 align-items-center mt-3 left-div">
|
||||
|
||||
<div class="col-auto">
|
||||
<label for="inputScrollSpeedZ" class="col-form-label"
|
||||
>Scroll Speed:
|
||||
@@ -2233,8 +2233,7 @@
|
||||
<div class="col-auto">
|
||||
<select
|
||||
id="inputScrollSpeed"
|
||||
class="form-select speed-select"
|
||||
>
|
||||
class="form-select speed-select">
|
||||
<option {%if stocks_settings.speed == 'medium' %} selected {% endif %}>Medium</option>
|
||||
<option {%if stocks_settings.speed == 'slow' %} selected {% endif %}>Slow</option>
|
||||
<option {%if stocks_settings.speed == 'fast' %} selected {% endif %}>Fast</option>
|
||||
@@ -2245,7 +2244,6 @@
|
||||
|
||||
|
||||
<div class="row g-3 align-items-center mt-3 left-div">
|
||||
|
||||
<div class="col-auto">
|
||||
<label for="inputScrollSpeedRowZ2" class="col-form-label"
|
||||
>Scroll Speed (Row 2):
|
||||
@@ -2255,8 +2253,7 @@
|
||||
<div class="col-auto">
|
||||
<select
|
||||
id="inputScrollSpeedRow"
|
||||
class="form-select speed-select"
|
||||
>
|
||||
class="form-select speed-select">
|
||||
<option {%if stocks_settings.speed2 == 'medium' %} selected {% endif %}>Medium</option>
|
||||
<option {%if stocks_settings.speed2 == 'slow' %} selected {% endif %}>Slow</option>
|
||||
<option {%if stocks_settings.speed2 == 'fast' %} selected {% endif %}>Fast</option>
|
||||
@@ -2278,8 +2275,7 @@
|
||||
<div class="col-auto">
|
||||
<select
|
||||
id="inputTransition"
|
||||
class="form-select animation-select"
|
||||
>
|
||||
class="form-select animation-select">
|
||||
<option {%if stocks_settings.animation == 'down' %} selected {% endif %}>Down</option>
|
||||
<option {%if stocks_settings.animation == 'up' %} selected {% endif %}>Up</option>
|
||||
<option {%if stocks_settings.animation == 'continuous' %} selected {% endif %}>Continuous</option>
|
||||
@@ -2305,8 +2301,7 @@
|
||||
id="inputText3"
|
||||
class="form-control"
|
||||
aria-describedby="TextHelpInline"
|
||||
placeholder="e.g. AAPL"
|
||||
/>
|
||||
placeholder="e.g. AAPL"/>
|
||||
</div>
|
||||
|
||||
<div class="col-auto">
|
||||
@@ -2692,6 +2687,302 @@
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Global Stocks -->
|
||||
|
||||
<div class="page" id="Page27" style="display: none">
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||
|
||||
<div class="row g-3 align-items-center mt-3 left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputScrollSpeedZ" class="col-form-label">Scroll Speed:</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select id="inputScrollSpeed27" class="form-select speed-select">
|
||||
<option {%if globalstocks_settings.speed == 'medium' %} selected {% endif %}>Medium</option>
|
||||
<option {%if globalstocks_settings.speed == 'slow' %} selected {% endif %}>Slow</option>
|
||||
<option {%if globalstocks_settings.speed == 'fast' %} selected {% endif %}>Fast</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center mt-3 left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputScrollSpeedRowZ2" class="col-form-label">Scroll Speed (Row 2):</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select id="inputScrollSpeedRow27" class="form-select speed-select">
|
||||
<option {%if globalstocks_settings.speed2 == 'medium' %} selected {% endif %}>Medium</option>
|
||||
<option {%if globalstocks_settings.speed2 == 'slow' %} selected {% endif %}>Slow</option>
|
||||
<option {%if globalstocks_settings.speed2 == 'fast' %} selected {% endif %}>Fast</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center mt-3 left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputTransitionZ" class="col-form-label">Intro Transition:</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select id="inputTransition27" class="form-select animation-select">
|
||||
<option {%if globalstocks_settings.animation == 'down' %} selected {% endif %}>Down</option>
|
||||
<option {%if globalstocks_settings.animation == 'up' %} selected {% endif %}>Up</option>
|
||||
<option {%if globalstocks_settings.animation == 'continuous' %} selected {% endif %}>Continuous</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center mt-3 left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputTextZ" class="col-form-label">Stock Symbol:</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input
|
||||
oninput="this.value = this.value.toUpperCase()"
|
||||
type="text"
|
||||
id="globalstocks_symbol"
|
||||
class="form-control"
|
||||
aria-describedby="TextHelpInline"
|
||||
placeholder="e.g. 0001.HK"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button id="globalstocks_symbol_addbtn" class="btn set-btn" onclick="globalstockValidate()">Add</button>
|
||||
</div>
|
||||
<p id="demo10" style="display: none"></p>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center mt-3 left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputText" class="col-form-label">Custom Logo:</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input
|
||||
type="file"
|
||||
id="globalstocks-logo-upload-browse"
|
||||
class="form-control"
|
||||
aria-describedby="TextHelpInline"
|
||||
placeholder="Browse"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button id="globalstocks-logo-upload-btn" class="btn set-btn" onclick="uploadGlobalStockLogo()">
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
<p id="globalstocklogoupload" style="color:red; display: none;">Global stock logo uploaded.</p>
|
||||
</div>
|
||||
|
||||
<div id="limit-msg"></div>
|
||||
|
||||
<div class="row g-3 align-items-center mt-3 left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputTransitionZ" class="col-form-label">Percent Change</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input
|
||||
class="form-check-input percent-select"
|
||||
type="checkbox"
|
||||
value=""
|
||||
id="globalstocks_percent"
|
||||
{%if globalstocks_settings.percent%} checked {%endif%} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputTransitionZ" class="col-form-label">Point Change</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input
|
||||
class="form-check-input point-select"
|
||||
type="checkbox"
|
||||
value=""
|
||||
id="globalstocks_point"
|
||||
{% if globalstocks_settings.point%} checked {%endif%} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputTransitionZ" class="col-form-label">Day Lo, Hi, Vol</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input
|
||||
class="form-check-input lohivol-select"
|
||||
type="checkbox"
|
||||
value=""
|
||||
id="globalstocks_lohivol"
|
||||
{% if globalstocks_settings.lohivol%} checked {%endif%} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputTransitionZ" class="col-form-label">Display Company Names</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input
|
||||
class="form-check-input name-select"
|
||||
type="checkbox"
|
||||
value=""
|
||||
id="globalstocks_displayname"
|
||||
{% if globalstocks_settings.display_name%} checked {%endif%}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputTransitionZ" class="col-form-label">Display Company Logos</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input
|
||||
class="form-check-input logo-select"
|
||||
type="checkbox"
|
||||
value=""
|
||||
id="globalstocks_displaylogos"
|
||||
{% if globalstocks_settings.logos%} checked {%endif%} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputTransitionZ" class="col-form-label">Display Feature Title</label>
|
||||
</div>
|
||||
|
||||
<div class="col-auto">
|
||||
<input
|
||||
class="form-check-input title-select"
|
||||
type="checkbox"
|
||||
value=""
|
||||
id="globalstocks_title"
|
||||
{% if globalstocks_settings.title%} checked {%endif%}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputTransitionZ" class="col-form-label">Display Portfolio</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input
|
||||
class="form-check-input portfolio-select"
|
||||
type="checkbox"
|
||||
value=""
|
||||
id="globalstocks_portfolio"
|
||||
{% if globalstocks_settings.chart%} checked {%endif%}
|
||||
onclick="globalportfolioValidate()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p id="demo-portfolio-globalstocks" style="display: none"></p>
|
||||
|
||||
<div id="globalstocks-portfolio" style="display: none;">
|
||||
<div class="row g-3 align-items-center mt-3 left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputTextZ" class="col-form-label">Shares:</label>
|
||||
</div>
|
||||
|
||||
<div class="col-auto">
|
||||
<input
|
||||
type="text"
|
||||
id="globalstocks_port_shares"
|
||||
class="form-control"
|
||||
aria-describedby="TextHelpInline"
|
||||
placeholder="e.g. 200" />
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button id="update-globalstock-port-btn" class="btn set-btn" onclick="updateGlobalStockPorftolio()">Update Position</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center mt-3 left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputTextZ" class="col-form-label">Avg Cost:</label>
|
||||
</div>
|
||||
|
||||
<div class="col-auto">
|
||||
<input
|
||||
type="text"
|
||||
id="globalstocks_port_cost"
|
||||
class="form-control"
|
||||
aria-describedby="TextHelpInline"
|
||||
placeholder="e.g. 152.45" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center mt-3 left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputTextZ" class="col-form-label">Date:</label>
|
||||
</div>
|
||||
|
||||
<div class="col-auto">
|
||||
<input
|
||||
type="text"
|
||||
id="globalstocks_port_date"
|
||||
class="form-control"
|
||||
aria-describedby="TextHelpInline"
|
||||
placeholder="e.g. YYYY-MM-DD" />
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button id="remove-globalstock-port-btn" class="btn set-btn" onclick="removeGlobalStockPorftolio()">Remove Position</button>
|
||||
</div>
|
||||
|
||||
<div id="updated-globalstock-p" style="display:none"><p id="globalstockupdated-p" style="color: red;">Global stock Position Updated!</p></div>
|
||||
<div id="removed-globalstock-p" style="display:none"><p id="globalstockremoved-p" style="color: red;">Global stock Position Removed!</p></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-md-4 col-sm-12">
|
||||
<h6 class="mt-3">List:</h6>
|
||||
<div class="features-div-two">
|
||||
<ul
|
||||
id="globalstocks-features"
|
||||
class="display-features-list text-white symbol-list">
|
||||
{% for f in globalstocks_settings.symbols %}
|
||||
<li onclick="getGlobalStockSymbol(this.innerText)">{{f}}</li>
|
||||
{% endfor%}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-2 col-md-2 col-sm-12">
|
||||
<div class="icons-list">
|
||||
<i
|
||||
id="globalstocks-increase-btn"
|
||||
class="upbutton fa fa-chevron-up"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<br />
|
||||
<br />
|
||||
<i
|
||||
id="globalstocks-decrease-btn"
|
||||
class="downbutton fa fa-chevron-down"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<a style="position: relative; bottom: 30px; left: 10px">Sort Order</a>
|
||||
<br />
|
||||
<br />
|
||||
<i id="globalstocks-remove-btn"
|
||||
class="fa fa-minus"
|
||||
aria-hidden="true"></i>
|
||||
<span style="position: relative; bottom: 0; left: 10px" >Remove</span >
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="save-btn-div">
|
||||
<a href="#" class="btn save-btn">Save</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Crypto -->
|
||||
|
||||
@@ -8848,6 +9139,142 @@
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- INSPIRATIONAL QUOTES -->
|
||||
|
||||
<div class="page" id="Page26" style="display: none">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||
|
||||
<div class="row g-3 align-items-center mt-3">
|
||||
<div class="col-auto">
|
||||
<label for="inputScrollSpeedZ222" class="col-form-label">Scroll Speed:</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select
|
||||
id="inputScrollSpeed26"
|
||||
class="form-select speed-select">
|
||||
<option {%if quotes_settings.speed == 'medium' %} selected {% endif %}>Medium</option>
|
||||
<option {%if quotes_settings.speed == 'slow' %} selected {% endif %}>Slow</option>
|
||||
<option {%if quotes_settings.speed == 'fast' %} selected {% endif %}>Fast</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center mt-3 left-div">
|
||||
<div class="col-auto">
|
||||
<label for="inputScrollSpeedRowZ222" class="col-form-label">Scroll Speed (Row 2):</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select
|
||||
id="inputScrollSpeedRow26"
|
||||
class="form-select speed-select">
|
||||
<option {%if quotes_settings.speed2 == 'medium' %} selected {% endif %}>Medium</option>
|
||||
<option {%if quotes_settings.speed2 == 'slow' %} selected {% endif %}>Slow</option>
|
||||
<option {%if quotes_settings.speed2 == 'fast' %} selected {% endif %}>Fast</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center mt-3">
|
||||
<div class="col-auto">
|
||||
<label for="inputTransitionZ222" class="col-form-label">Intro Transition:
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select id="inputTransition26" class="form-select animation-select">
|
||||
<option {%if quotes_settings.animation == 'down' %} selected {% endif %}>Down</option>
|
||||
<option {%if quotes_settings.animation == 'up' %} selected {% endif %}>Up</option>
|
||||
<option {%if quotes_settings.animation == 'continuous' %} selected {% endif %}>Continuous</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center left-div" style="padding-top: 25px;">
|
||||
<div class="col-auto">
|
||||
<label for="inputTransitionZ222" class="col-form-label">
|
||||
Display Feature Title
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input
|
||||
class="form-check-input title-select"
|
||||
type="checkbox"
|
||||
value=""
|
||||
id="quotes_settings_title"
|
||||
{% if quotes_settings.title%}
|
||||
checked
|
||||
{%endif%}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 align-items-center mt-3">
|
||||
<div class="col-auto">
|
||||
<label for="quotes-amount" class="col-form-label">Amount: </label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select id="quotes-amount" class="form-select quotes-amount-select">
|
||||
<option {%if quotes_settings.amount == '1' %} selected {% endif %}>1</option>
|
||||
<option {%if quotes_settings.amount == '2' %} selected {% endif %}>2</option>
|
||||
<option {%if quotes_settings.amount == '3' %} selected {% endif %}>3</option>
|
||||
<option {%if quotes_settings.amount == '4' %} selected {% endif %}>4</option>
|
||||
<option {%if quotes_settings.amount == '5' %} selected {% endif %}>5</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-4 col-md-4 col-sm-12">
|
||||
<h6 class="mt-3">List:</h6>
|
||||
<div class="features-div-two">
|
||||
<ul
|
||||
id="quotes-list"
|
||||
class="display-features-list text-white symbol-list">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-2 col-md-2 col-sm-12">
|
||||
<div class="icons-list">
|
||||
<i
|
||||
id="quotes-increase-btn"
|
||||
class="upbutton fa fa-chevron-up"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<br />
|
||||
<br />
|
||||
<i
|
||||
id="quotes-decrease-btn"
|
||||
class="downbutton fa fa-chevron-down"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<a style="position: relative; bottom: 30px; left: 10px">Sort Order</a>
|
||||
<br />
|
||||
<br />
|
||||
<i
|
||||
id="quotes-remove-btn"
|
||||
class="fa fa-minus"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span style="position: relative; bottom: 0; left: 10px">Remove</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="save-btn-div">
|
||||
<a href="#" class="btn save-btn">Save</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Custom Images -->
|
||||
@@ -10432,7 +10859,7 @@
|
||||
|
||||
<p>© 2020-2023 Fintic Limited., All Rights Reserved. <a href="mailto:info@fintic.io" id="footerlinks">Contact Us.</a></p>
|
||||
|
||||
<p>Data Provided by TradingView, IEX Cloud, Open-Meteo, CoinGecko, Exchangerate-API, TheSportsDB, Google News, <br>Yahoo Finance, ESPN, The Movie DB, Finnhub, Sv443 (JokeAPI), r/place, r/thefinalclean</p>
|
||||
<p>Data Provided by TradingView, IEX Cloud, Open-Meteo, CoinGecko, Exchangerate-API, TheSportsDB, Google News, <br>Yahoo Finance, ESPN, The Movie DB, Finnhub, Sv443 (JokeAPI), r/place, r/thefinalclean, ZenQuotes API</p>
|
||||
|
||||
<p>Useful resources: <a href="https://www.youtube.com/playlist?list=PLf8pW0bNjnebNZh3y0AsY18sxJj6IhAsv" id="footerlinks" target="_blank">YouTube Tutorials</a> , <a href="https://docs.google.com/spreadsheets/d/1IZkEl49j97xvG8jcEdWc5XdOLOUb_-ZLVHle2vezWCc/edit?usp=sharing" id="footerlinks" target="_blank">Formatting Guide & Info</a> , <a href="https://fintic.io" id="footerlinks" target="_blank">Official Website</a></p>
|
||||
|
||||
@@ -10446,7 +10873,7 @@
|
||||
<script src="{{ url_for('static', filename='js/jquery-2.1.1.js') }}"></script>
|
||||
|
||||
<!-- <script src="{{ url_for('static', filename='app.js') }}"></script>. ALWAYS CHANGE VERSIONING WHENEVER CHANGES ARE MADE TO AVOID BAD CACHING -->
|
||||
<script type='text/javascript' src='../static/app.js?ver=1.3.8'></script>
|
||||
<script type='text/javascript' src='../static/app.js?ver=1.3.9'></script>
|
||||
|
||||
<script>
|
||||
|
||||
|