Beispiel #1
0
 def __init__(self, record_to_request: str, input_type='iupac_name'):
     if search_validate(input_type):  #in pubchem_search_types:
         if TESTING == True:
             greenprint("searching for a Description : " +
                        record_to_request)
         if input_type == "iupac_name":
             self.thing_type = "name"
         else:
             self.thing_type = input_type
     self.record_to_request = record_to_request
     self.request_url         = requote_uri("{}/compound/{}/{}/description/XML".format(\
                                 API_BASE_URL,self.thing_type,self.record_to_request))
     blueprint("[+] Requesting: " + makered(self.request_url) + "\n")
     self.request_return = requests.get(self.request_url)
     self.soupyresults = BeautifulSoup(self.request_return.text,
                                       features='lxml').contents[1]
     self.parsed_result = self.soupyresults.find_all(
         lambda tag: tag.name == 'description')
     if self.parsed_result != []:
         self.parsed_result = str(self.parsed_result[0].contents[0])
         greenprint("[+] Description Found!")
         print(self.parsed_result)
     elif self.parsed_result == [] or NoneType:
         blueprint("[-] No Description Available in XML REST response")
         self.parsed_result = "No Description Available in XML REST response"
Beispiel #2
0
    def decode_and_save(self, base64_image, name, image_format):
        '''
Decodes a base64 string to an image and saves that
This helps display images in discord because they suck
and dont allow base64 as a uri anymore
        '''
        greenprint("[+] Decoding and Saving image as {}".format(name))
        decoded_image = self.decode_image_from_base64(base64_image)
        decoded_image.save(name, format=image_format)
Beispiel #3
0
    def encode_image_to_base64(self, image, image_format="png"):
        '''
    stack overflow post
    https://stackoverflow.com/questions/52411503/convert-image-to-base64-using-python-pil   

        '''
        greenprint("[+] Encoding Image as Base64")
        buff = BytesIO()
        image.save(buff, format=image_format)
        img_str = base64.b64encode(buff.getvalue())
        return img_str
Beispiel #4
0
 def __init__(self,
              record_to_request: str,
              image_as_base64=True,
              input_type="name",
              temp_file="image"):
     #############################
     if search_validate(input_type):  #in pubchem_search_types:
         greenprint("searching for an image : " + record_to_request)
         # fixes local code/context to work with url/remote context
         if input_type == "iupac_name":
             self.input_type = "name"
         else:
             self.input_type = input_type
         self.request_url        = requote_uri("{}/compound/{}/{}/PNG".format(\
                                         API_BASE_URL,self.input_type,record_to_request))
         blueprint("[+] Requesting: " + makered(self.request_url))
         self.rest_request = requests.get(self.request_url)
         if self.was_there_was_an_error() == False:
             # request good
             # Store image
             # we want an image file
             if image_as_base64 == False:
                 try:
                     self.filename = temp_file + ".png"
                     greenprint("[+] Saving image as {}".format(
                         self.filename))
                     self.image_storage = Image.open(
                         BytesIO(self.rest_request.content))
                     self.image_storage.save(self.filename, format="png")
                     self.image_storage.close()
                 except Exception as derp:
                     redprint(
                         "[-] Exception when opening or writing image file")
                     print(derp)
         # we want a base64 string
             elif image_as_base64 == True:
                 self.image_storage = self.encode_image_to_base64(
                     self.image_storage)
             else:
                 redprint("[-] Error with Class Variable self.base64_save")
     else:
         redprint("[-] Input type was wrong for Image Search")
         return None
Beispiel #5
0
 def internal_local_database_lookup(entity: str, id_of_record: str):
     """
     feed it a formula or CID followed buy "formula" or "cid" or "iupac_name
     searches by record and entry
     Returns False and raises and exception/prints exception on error
     Returns an SQLAlchemy database object if record exists
     Don't forget this is for compounds only!
     """
     try:
         greenprint("[+] performing internal lookup")
         if search_validate(id_of_record):  # in pubchem_search_types:
             kwargs = {id_of_record: entity}
             lookup_result = Compound.query.filter_by(**kwargs).first()
             #lookup_result  = database.Compound.query.filter_by(id_of_record = entity).first()
         return lookup_result
     except Exception as derp:
         print(derp)
         redprint("[-] Not in local database")
         # None if empty
         return None
Beispiel #6
0
    def validate_user_input(self, user_input: str, type_of_input: str):
        """
User Input is expected to be the proper identifier.
    type of input is one of the following: cid , iupac_name , cas

Ater validation, the user input is used in :
    Pubchem_lookup.do_lookup()
        Pubchem_lookup.pubchem_lookup_by_name_or_CID()
        
        """
        import re
        cas_regex = re.compile('[1-9]{1}[0-9]{1,5}-\d{2}-\d')
        if search_validate(type_of_input):  #in pubchem_search_types:
            greenprint("user supplied a : " + type_of_input)
            try:
                if type_of_input == "cas":
                    greenprint(
                        "[+} trying to match regular expression for CAS")
                    if re.match(cas_regex, user_input):
                        greenprint("[+] Good CAS Number")
                        self.do_lookup(user_input, type_of_input)
                    else:
                        redprint("[-] Bad CAS Number")
                        self.user_input_was_wrong("bad_CAS", user_input)
                elif type_of_input == "cid" or "iupac_name":
                    self.do_lookup(user_input, type_of_input)
                else:
                    redprint(
                        "[-] Something really wierd happened inside the validation flow"
                    )
            except Exception as derp:
                redprint("[-] reached the exception ")
                print(derp)
        else:
            self.user_input_was_wrong("input_type", type_of_input)
Beispiel #7
0
    def __repr__(self):
        list_to_string = lambda list_to_convert: ''.join(list_to_convert)
        formula_list = str.split(self.compounds, sep=",")
        greenprint(formula_list)
        formula = ""

        # what the hell was I doing here?
        # seriously, I forgot
        def format_asdf():
            for each in formula_list:
                #catches the amount
                if list_to_string(each).isnumeric():
                    amount = list_to_string(str(each))
                #catches the element/compound
                else:
                    compound = str(each)
                formula + '{} : {} {}'.format(compound, amount, "\n\t")

        return 'Composition: {} \n\
Units: {} \n\
Formula: {} \n\
Notes: {}'.format(self.name, self.units, formula, self.notes)
Beispiel #8
0
    def __init__(self,
                 record_to_request: str,
                 image_as_base64: bool,
                 input_type="name",
                 temp_file="image"):
        #############################
        # greenprint("[+] Running as Discord Attachment")
        # greenprint("[+] Not running as Discord Attachment")
        #print(str(os.environ['DISCORDAPP']))
        if image_as_base64 == False:
            self.filename = temp_file + ".png"
        if search_validate(input_type):  #in pubchem_search_types:
            greenprint("searching for an image : " + record_to_request)
            # fixes local code/context to work with url/remote context
            if input_type == "iupac_name":
                self.input_type = "name"
            else:
                self.input_type = input_type
            self.request_url        = requote_uri("{}/compound/{}/{}/PNG".format(\
                                            API_BASE_URL,self.input_type,record_to_request))
            blueprint("[+] Requesting: " + makered(self.request_url))
            self.rest_request = requests.get(self.request_url)
            # redprint("[-] Request failure at local level")
            # True means no error
            if self.was_there_was_an_error() == True:
                # request good
                # Store image
                self.image_storage = Image.open(
                    BytesIO(self.rest_request.content))
                if image_as_base64 == False:
                    try:
                        greenprint("[+] Saving image as {}".format(
                            self.filename))
                        self.image_storage.save(self.filename, format="png")
                    except Exception as blorp:
                        redprint(
                            "[-] Exception when opening or writing image file")
                        print(blorp)
                elif image_as_base64 == True:
                    print(self.rest_request.raw)
                    greenprint("[+] Encoding Image as Base64")
                    self.image_storage = base64.b64encode(self.image_storage)

                else:
                    redprint("[-] Error with Class Variable self.base64_save")
        else:
            redprint("[-] Input type was wrong for Image Search")
            return None
Beispiel #9
0

###############################################################################
    def composition_to_database(comp_name: str, units_used :str, \
                                formula_list : list , info : str):
        """
        The composition is a relation between multiple Compounds
        Each Composition entry will have required a pubchem_lookup on each
        Compound in the Formula field. 
        the formula_list is a CSV STRING WHERE: 
        ...str_compound,int_amount,.. REPEATING (floats allowed)
        EXAMPLE : Al,27.7,NH4ClO4,72.3

        BIG TODO: be able to input list of cas/cid/whatever for formula_list
        """
        # query local database for records before performing pubchem
        # lookups
        # expected to return FALSE if no record found
        # if something is there, it will evaluate to true
        #        for each in formula_list:
        #            input = Pubchem_lookup.formula_input_validation(each)

        # extend this but dont forget to add more fields in the database model!
        Database_functions.add_to_db(Composition(\
                name       = comp_name,               \
                units      = units_used,              \
                compounds  = formula_list,            \
                notes      = info                     ))

greenprint("[+] Loaded database")
Beispiel #10
0
    if DISPLAY_FROM_BASE64 == True:
        from discord import Attachment

        #image_string = 'data:image/png;base64,{}'.format(str(new_lookup.lookup_object.image))
        #image_string = 'data:image/png;base64,'+ str(new_lookup.lookup_object.image)
        #pubchem_embed.set_image(url='data:image/png;base64,{}'.format(str(new_lookup.lookup_object.image)))
        asdf = Attachment(data='image/png;base64,{}'.format(str(new_lookup.lookup_object.image)))
        #await ctx.send(content=new_lookup.image, embed=pubchem_embed)
        await ctx.send(content=asdf, embed=pubchem_embed)
@lookup_bot.command()
async def balance_equation(ctx, arg1):
    EquationBalancer.validate_formula_input(arg1)
    await ctx.send(lookup_output_container)


greenprint("[+] Loaded Discord commands")

################################################################################
# AND NOW WE RUN THE BOT!!! YAY!!! I HAVE MORE DEBUGGING TO DO!!########
from variables_for_reality import TESTING
from variables_for_reality import SAVE_BASE64

if TESTING == True:
    lookup_bot.run(discord_key.discord_bot_token, bot=True)
else:
    try:
        if __name__ == '__main__':
            SAVE_BASE64 = True
            DISPLAY_FROM_BASE64 = False
            lookup_bot.run(discord_key.discord_bot_token, bot=True)
        else:
Beispiel #11
0
    def pubchem_lookup_by_name_or_CID(self, compound_id, type_of_data: str):
        '''
        Provide a search term and record type
        requests can be CAS,CID,IUPAC NAME/SYNONYM

        outputs in the following order:
        CID, CAS, SMILES, Formula, Name

        Stores lookup in database if lookup is valid
        '''
        return_relationships = []
        # you get multiple records returned from a pubchem search VERY often
        # so you have to choose the best one to store, This needs to be
        # presented as an option to the user,and not programmatically
        # return_index is the result to return, 0 is the first one
        return_index = 0
        data = ["iupac_name", "cid", "cas"]
        if type_of_data in data:
            # different methods are used depending on the type of input
            # one way
            if type_of_data == ("iupac_name" or "cas"):
                try:
                    greenprint("[+] Performing Pubchem Query")
                    lookup_results = pubchem.get_compounds(compound_id, 'name')
                except Exception:  # pubchem.PubChemPyError:
                    redprint(
                        "[-] Error in pubchem_lookup_by_name_or_CID : NAME exception"
                    )
                    self.user_input_was_wrong("pubchem_lookup_by_name_or_CID")
        # CID requires another way
            elif type_of_data == "cid":
                try:
                    greenprint("[+] Performing Pubchem Query")
                    lookup_results = pubchem.Compound.from_cid(compound_id)
                except Exception:  # pubchem.PubChemPyError:
                    redprint("lookup by NAME/CAS exception - name")
                    self.user_input_was_wrong("pubchem_lookup_by_name_or_CID")
        # once we have the lookup results, do something
            if isinstance(lookup_results,
                          list):  # and len(lookup_results) > 1 :
                greenprint("[+] Multiple results returned ")
                for each in lookup_results:
                    query_appendix = [{'cid' : each.cid                                 ,\
                            #'cas'                     : each.cas                       ,\
                            'smiles'                   : each.isomeric_smiles           ,\
                            'formula'                  : each.molecular_formula         ,\
                            'molweight'                : each.molecular_weight          ,\
                            'charge'                   : each.charge                    ,\
                            'bond_stereo_count'        : each.bond_stereo_count         ,\
                            'bonds'                    : each.bonds                     ,\
                            'rotatable_bond_count'     : each.rotatable_bond_count      ,\
                            'multipoles_3d'            : each.multipoles_3d             ,\
                            'mmff94_energy_3d'         : each.mmff94_energy_3d          ,\
                            'mmff94_partial_charges_3d': each.mmff94_partial_charges_3d ,\
                            'atom_stereo_count'        : each.atom_stereo_count         ,\
                            'h_bond_acceptor_count'    : each.h_bond_acceptor_count     ,\
                            'feature_selfoverlap_3d'   : each.feature_selfoverlap_3d    ,\
                            'cactvs_fingerprint'       : each.cactvs_fingerprint        ,\
                            'iupac_name'               : each.iupac_name                ,\
                            'description'              : self.lookup_description        ,\
                            'image'                    : self.image                     }]
                    return_relationships.append(query_appendix)
                    # Right here we need to find a way to store multiple records
                    # and determine the best record to store as the main entry
                    #compound_to_database() TAKES A LIST!!! First element of first element
                    #[ [this thing here] , [not this one] ]
                    #print(return_relationships[return_index])
                    Database_functions.compound_to_database(
                        return_relationships[return_index])

            # if there was only one result or the user supplied a CID for a single chemical
            elif isinstance(lookup_results, pubchem.Compound):  #\
                #or (len(lookup_results) == 1 and isinstance(lookup_results, list)) :
                greenprint("[+] One Result Returned!")
                query_appendix = [{'cid'               : lookup_results.cid                 ,\
                            #'cas'                     : lookup_results.cas                 ,\
                            'smiles'                   : lookup_results.isomeric_smiles     ,\
                            'formula'                  : lookup_results.molecular_formula   ,\
                            'molweight'                : lookup_results.molecular_weight    ,\
                            'charge'                   : lookup_results.charge              ,\
                            'bond_stereo_count'        : each.bond_stereo_count             ,\
                            'bonds'                    : each.bonds                         ,\
                            'rotatable_bond_count'     : each.rotatable_bond_count          ,\
                            'multipoles_3d'            : each.multipoles_3d                 ,\
                            'mmff94_energy_3d'         : each.mmff94_energy_3d              ,\
                            'mmff94_partial_charges_3d': each.mmff94_partial_charges_3d     ,\
                            'atom_stereo_count'        : each.atom_stereo_count             ,\
                            'h_bond_acceptor_count'    : each.h_bond_acceptor_count         ,\
                            'feature_selfoverlap_3d'   : each.feature_selfoverlap_3d        ,\
                            'cactvs_fingerprint'       : each.cactvs_fingerprint            ,\
                            'iupac_name'               : each.iupac_name                    ,\
                            'description'              : self.lookup_description            ,\
                            'iupac_name'  : lookup_results.iupac_name                       ,\
                            # Local stuff

                            'description' : self.lookup_description                         ,\
                            'image'       : self.image                                      }]
                return_relationships.append(query_appendix)
                #print(query_appendix)
                Database_functions.compound_to_database(
                    return_relationships[return_index])
            else:
                redprint("PUBCHEM LOOKUP BY CID : ELSE AT THE END")
    #after storing the lookup to the local database, retrive the local entry
    #This returns an SQLALchemy object
        return_query = return_relationships[return_index]
        query_cid = return_query[0].get('cid')
        local_query = Compound.query.filter_by(cid=query_cid).first()
        return local_query
Beispiel #12
0
 def do_lookup(self, user_input, type_of_input):
     '''
     after validation, the user input is used in 
     Pubchem_lookup.pubchem_lookup_by_name_or_CID() 
     pubchemREST_Description_Request(user_input, type_of_input)
     Image_lookup()
     '''
     try:
         internal_lookup = Database_functions.internal_local_database_lookup(
             user_input, type_of_input)
         # if internal lookup is false, we do a remote lookup and then store the result
         if internal_lookup == None or False:
             redprint("[-] Internal Lookup returned false")
             self.internal_lookup_bool = False
             # we grab things in the proper order
             # description first
             try:
                 description_lookup = pubchemREST_Description_Request(
                     user_input, type_of_input)
             except Exception as derp:
                 redprint("[-] Description Lookup Failed")
                 print(derp)
                 self.lookup_description = "Description Lookup Failed"
             #then image
             try:
                 #if (SAVE_BASE64 == True) :
                 image_lookup            = Image_lookup(user_input               ,\
                                                         image_as_base64 = True     ,\
                                                         input_type      = type_of_input ,\
                                                         temp_file       = user_input      )
             except Exception as derp:
                 redprint("[-] Image Lookup Failed")
                 print(derp)
                 image_lookup = None
         # no image
             if image_lookup == None:
                 self.image = "No Image Available"
         # image as base64
             elif (image_lookup != None) and (DISPLAY_FROM_BASE64 == True):
                 self.image = str(image_lookup.image_storage)
         # image as file
             elif (image_lookup != None) and (DISPLAY_FROM_BASE64 == False):
                 self.image = image_lookup.image_storage
                 self.image_filename = image_lookup.filename
             else:
                 redprint("[-] Something wierd happened in do_lookup")
             # Now pubchem
             self.lookup_description = description_lookup.parsed_result
             self.lookup_object = self.pubchem_lookup_by_name_or_CID(
                 user_input, type_of_input)
         # we return the internal lookup if the entry is already in the DB
         # for some reason, asking if it's true doesn't work here so we use a NOT instead of an Equals.
         elif internal_lookup != None or False:
             greenprint("[+] Internal Lookup returned TRUE")
             self.internal_lookup_bool = True
             self.lookup_description = internal_lookup.description
             self.lookup_object = internal_lookup
             self.image = internal_lookup.image
             #redprint("==BEGINNING==return query for DB lookup===========")
             #greenprint(str(internal_lookup))
             #redprint("=====END=====return query for DB lookup===========")
     # its in dire need of proper exception handling
     except Exception as derp:
         redprint(
             '[-] Something happened in the try/except block for the function do_lookup'
         )
         print(derp)
Beispiel #13
0
 def save_image(self, PIL_image, name, image_format):
     '''
 Saves image
     '''
     greenprint("[+] Saving image as {}".format(name))
     PIL_image.save(self.filename, format=image_format)
Beispiel #14
0
    #after storing the lookup to the local database, retrive the local entry
    #This returns an SQLALchemy object
        return_query = return_relationships[return_index]
        query_cid = return_query[0].get('cid')
        local_query = Compound.query.filter_by(cid=query_cid).first()
        return local_query

    # OR return the remote lookup entry, either way, the information was stored
    # and you get a common "api" to draw data from.


###############################################################################
# TODO: Testing procedure requires bad data craft a list of shitty things a
# user can attempt. Be malicious and stupid with it
# break shit
greenprint("[+] Loaded Pubchem Lookup")

try:
    if __name__ == '__main__':
        if TESTING == True:
            import time
            #craft a list of queries to test with
            test_query_list = [["420","cid"],\
                ["methanol","iupac_name"],\
                ["phenol","iupac_name"],\
                ["methylene chloride","iupac_name"] ,\
                ["6623","cid"],\
                ["5462309","cid"],\
                ["24823","cid"],\
                ["water","iupac_name"]]
    ###################################################################