DispenseInterface and OpenDispense Implimentation created and tested. Not curruntly...
[uccvend-vendserver.git] / VendServer / OpenDispense.py
diff --git a/VendServer/OpenDispense.py b/VendServer/OpenDispense.py
new file mode 100644 (file)
index 0000000..f8cee0d
--- /dev/null
@@ -0,0 +1,126 @@
+from DispenseInterface import DispenseInterface
+import os
+import re
+import pwd
+from subprocess import Popen, PIPE
+from LDAPConnector import get_uid,get_uname, set_card_id
+
+"""
+Author: Mitchell Pomery (bobgeorge33)
+
+System to connect to OpenDispense2.
+Most of this code has been copied out of VendServer.py, then had variables updated so that it runs.
+This is so VendServer can easily operate regardless of the current accounting backend.
+Documentation for this code can be found inder Dispence.DispenceInterface
+"""
+class OpenDispense(DispenseInterface):
+        _username = None
+        _disabled = True
+        _loggedIn = False
+       _userId = None
+
+        def __init__(self, userId=None, username=None, loggedIn=False):
+               self._username = username
+                self._loggedIn = loggedIn
+               self._userId = userId
+               
+               acct, unused = Popen(['dispense', 'acct', self._username], close_fds=True, stdout=PIPE).communicate()
+               # this is fucking appalling
+               flags = acct[acct.find("(")+1:acct.find(")")].strip()
+               if 'disabled' in flags:
+                       self._disabled = True
+               if 'internal' in flags:
+                       self._disabled = True
+                self._disabled = False
+
+       @staticmethod
+       def authUserIdPin(userId, pin):
+               try:
+                       # Get info from 
+                        info = pwd.getpwuid(userId)
+                except KeyError:
+                        logging.info('getting pin for uid %d: user not in password file'%uid)
+                        return None
+
+                if info.pw_dir == None: return False
+                pinfile = os.path.join(info.pw_dir, '.pin')
+                try:
+                        s = os.stat(pinfile)
+                except OSError:
+                        logging.info('getting pin for uid %d: .pin not found in home directory'%uid)
+                        return None
+                if s.st_mode & 077:
+                        logging.info('getting pin for uid %d: .pin has wrong permissions. Fixing.'%uid)
+                        os.chmod(pinfile, 0600)
+                try:
+                        f = file(pinfile)
+                except IOError:
+                        logging.info('getting pin for uid %d: I cannot read pin file'%uid)
+                        return None
+                pinstr = f.readline().strip()
+                f.close()
+                if not re.search('^[0-9]{4}$', pinstr):
+                        logging.info('getting pin for uid %d: %s not a good pin'%(uid,repr(pinstr)))
+                        return None
+               return OpenDispense(userId, info.pw_name, (int(pin)==int(pinstr)))
+
+       @staticmethod
+       def authMifareCard(cardId):
+               return OpenDispense(get_uid(cardId), get_uname(get_uid(cardId)), True)
+
+       def addCard(self, cardId):
+               set_card_id(self._userId, cardId)
+
+        def isLoggedIn(self):
+                return self._loggedIn
+
+        def getUsername(self):
+                return self._username
+
+        def getBalance(self):
+               # Balance checking
+                acct, unused = Popen(['dispense', 'acct', self._username], close_fds=True, stdout=PIPE).communicate()
+                # this is fucking appalling
+                balance = acct[acct.find("$")+1:acct.find("(")].strip()
+                return balance
+
+        def getItemInfo(itemId):
+               itemId = OpenDispenseMapping.vendingMachineToOpenDispense(itemId)
+               args = ('dispense', 'iteminfo', itemId)
+                info, unused = Popen(args, close_fds=True, stdout=PIPE).communicate()
+                m = re.match("\s*[a-z]+:\d+\s+(\d+)\.(\d\d)\s+([^\n]+)", info)
+                cents = int(m.group(1))*100 + int(m.group(2))
+               # return (name, price in cents)
+                return (m.group(3), cents)
+
+        def isDisabled(self):
+               return False
+
+        def dispenseItem(self, itemId):
+               itemId = OpenDispenseMapping.vendingMachineToOpenDispense(itemId)
+               if itemId == "":
+                       return False
+               else:
+                       print('dispense -u "%s" %s'%(self._username, itemId))
+                       os.system('dispense -u "%s" %s'%(self._username, itemId))
+                       return True
+
+"""
+This class abstracts the idea of item numbers.
+It removes the need for VendServer to know the mappings between inputted numbers
+and the equivalent itemId in OpenDispense.
+"""
+class OpenDispenseMapping():
+
+       @staticmethod
+       def vendingMachineToOpenDispense(itemId):
+               _mappingFile = "OpenDispenseMappings.conf"
+               fh = open(_mappingFile)
+               map = ""
+               for line in fh:
+                       #line = line.strip()
+                       if line.startswith(str(itemId) + " "):
+                               map = line[len(str(itemId)) + 1:].strip()
+                               print(map)
+               return map
+

UCC git Repository :: git.ucc.asn.au