#!/usr/bin/env python3
#=====================================================================================
# Get a stock quote from  https://www.cnbc.com/quotes/
# symbol is passed via HTTP parameters  (e.g. url/symbol)
# Data returned as a JSON, format:  
# {
#    "header": {
#         "symbol": "AAPL",
#         "name": "Apple Inc",
#         "message": "",
#         "date_time": "2017-10-15 19:15:38.416224"
#     },
#     "data": [
#         {
#             "stock": "AAPL",
#             "last_price": "156.99",
#             "date": "10/15/2017",
#             "time": "19:15:38"
#         }
#     ]
# }
#===================================================================================== 
from datetime import datetime                       #to obtain date and time
import cgi                                          #cgi 
import cgitb                                        #cgi with traceback error handling
import urllib.request                               #urllib.request module allows fetching of urls 
import json                                         #to convert a python dict/array to a json string 
cgitb.enable()
 
print("Content-Type: text/plain \n")                #required http response header (w/ extra line)

elements = cgi.FieldStorage()                       #obtain the http for elements
symbol   = elements.getvalue('symbol') or 'AAPL'    #entry field, if empty use 'GOOG'            
 
url = "https://www.cnbc.com/quotes/"				#The URL to call 

start1     = 0										#begin searching after 0 characters
searchFor1 = '"Corporation"'                        #string to look for 
offset1    = 22                                     #the offset which is 16 characters
end1       = '"'

start2     = 0                                      #begin searching after 0 characters                                    
searchFor2 = '"last"'                               #string to look for 
offset2    = 8                                      #the offset which is 8 characters
end2       = '"'                                    #string to look for 

msg  = ''                                           #Error message   - global variable

#-------------------------------------------------------------------------------------
# Function to retrieve a URL from the web
#-------------------------------------------------------------------------------------
def getURL(url):
    global msg                                    #needed to modify global variable

    url2 = url + symbol
#   print(url2)
    try:
        resource = urllib.request.urlopen(url2)   #send the request
        page     = resource.read()                #read the returned data (in bytes type)
    except:
        msg   = "Could not retrieve URL"
        page  = ""
       
    page = page.decode('ascii', 'ignore')         #convert Byte type to String 

    return(page)

#-------------------------------------------------------------------------------------
# Function to obtain the company name of the stock
#-------------------------------------------------------------------------------------
def getName(page):
    global msg                                 #needed to modify global variable

    try:                                       #if not found
        found = page.index(searchFor1,start1)  #find the search string, starting after x number of char
        start = found + offset1                #add the offset
        end   = page.index(end1,start)         #look for the end string 
        name  = page[start : end]              #substring
    except:
        msg   = 'stock name not found'
        name = ""
       
#   print(name)
    return(name)
    
#-------------------------------------------------------------------------------------
# Function to obtain the latest stock price from the web page
#-------------------------------------------------------------------------------------
def getQuote(page):
    global msg                                 #needed to modify global variable

    try:                                       #if not found
        found = page.index(searchFor2,start2)  #find the search string, starting after x number of char
        start = found + offset2                #add the offset
        end   = page.index(end2,start)         #look for the end string
        quote = page[start : end]              #substring 
    except:
        msg   = "stock price not found"
        quote = ""
       
#   print(quote)
    return(quote)

#-------------------------------------------------------------------------------------
# Function to send the quote back to the requestor
#-------------------------------------------------------------------------------------
def send(quote):
    global msg                              #needed to modify global variable
                                           
    response = {}                           #the overall response 
    header   = {}                           #the header component
    data     = []                           #the data component

    now = datetime.now()                    #current timestamp object
    
    if symbol=='NONE':
        msg = 'No stock symbol provided. Enter url?symbol=name'

    header['symbol']    = symbol.upper()
    header['name']      = name
    header['message']   = msg 
    header['date_time'] = str(now.date()) +' '+ str(now.time())

    dict = {}
    dict['stock']      = symbol.upper()             #convert to upper case
    dict['last_price'] = quote
    dict['name']       = name
    dict['date']       = F"{now.month}/{now.day}/{now.year}"
    dict['time']       = F"{now.hour}:{now.minute:02d}:{now.second:02d}"

    data.append(dict)                               #add dictionary to data array
    
    response['header'] = header                     #add the headers
    response['data']   = data                       #add the stock info

    jsonStr = json.dumps(response,indent=4)         #create a JSON string
    print(jsonStr)                                  #print it

#-------------------------------------------------------------------------------------
# Main code
#-------------------------------------------------------------------------------------

page  = ''
name  = ''
quote = ''

page  = getURL(url)                             #retrieve the url
name  = getName(page)                           #obtain the name of the stock
quote = getQuote(page)                          #obtain the stock's latest price

send(quote)                                     #send the quote back to requestor

#================================================================================