pyss Python Sms Script

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Clython
User
Beiträge: 151
Registriert: Samstag 21. August 2004, 13:58
Wohnort: Schweiz, BE-2500

Hallo Leute

mein Kumpel hat herausgefunden wie man mit Hilfe von smssend http://zekiller.skytech.org/smssend_menu_en.html über unseren Mobile-Provider gratis SMS verschicken kann und dazu ein kleines bash-Script geschrieben. Da der Funktionsumfang etwas ungenügend war, habe ich ein Python-Frontend dazu geschrieben.
pyss unterstützt das erstellen eines Adressbuches, das Personen und Gruppen enthalten kann und hat eine simple Log-Funktionalität. Ausserdem splitet es eine Nachricht automatisch auf die richtige Grösse, ohne Wörter zu zerhacken!

Seht es euch mal an:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF8 -*-

# pyss version 0.2
# Author: Maël Mettler
# Home: www.mediamonger.ch
# e-mail: pyss@mediamonger.ch
# License: GNU v2

import sys
import os
import getopt
import pickle

class manageaccount:
    "This class is used to manage the account information."
    def __init__(self, account):
        "The account information is contained in a tuple with 4 fields. Fields 0-3 are dictionaries (persons, groups and settings), field 3 is a list with the log data."
        self.book = account
        
    def showentry(self, section):
        "Shows all entries of a section"
        l = []
        for item in self.book[section]:
            l.append(item)
        l.sort()
        i = 0
        for item in l:
            length = len(item)
            space = 15 - length
            print i, item, space*" ", self.book[section][item]
            i = i + 1
        
    def addentry(self, key, value, section):
        "Adds entry [key] with value [value] to [section]"
        newentry = { key : value }
        self.book[section].update(newentry)
        
    def delentry(self, key, section):
        "Deletes entry with key [key] in [section]"
        del self.book[section][key]
    
    def changeentry(self, key, newvalue, section):
        "Changes entry with [key] to [newvalue] in [section]"
        self.book[section][key]
        newentry = { key : newvalue }
        self.book[section].update(newentry)

class processsms:
    "This class provides the functionalities to transform user input into data that sendsms can handle"
    def __init__(self, data, message, recipients):
        "Processsms takes 3 arguments: the data-dictionary, the message as a string and a list of recipients"
        self.m = message
        self.r = recipients
        self.b = data
        
        
    def getnumbers(self):
        "This function resolves persons and groups to phonenumbers"
        numbers = []
        for item in self.r:
            if self.b[0].has_key(item):
                r1 = self.b[0][item], 1
                numbers.append(r1)
            elif self.b[1].has_key(item):
                for i in self.b[1][item]:
                    r2 = self.b[0][i], 1
                    numbers.append(r2)
            else:
                if ismn(item):
                    r3 = ismn(item), 0
                    numbers.append(r3)
                else:
                    numbers.append(item, 2)
        numberofrecipients = len(numbers)
        indexend = numberofrecipients - 1
        x = self.demodulo(numberofrecipients, 9)
        result = []
        i = 1
        while i <= x:
            start = 9*(i-1)
            end = (i*9)
            if end > indexend:
                end = indexend
            else:
                pass
            result.append(numbers[9*(i-1) : (i*9)])
            i = i + 1            
        return result
                
    def tokenizemessage(self):
        "This function splits the message to pieces smaller than 160 digits. If there is more than one piece then tokenizemessage adds pagecounts (ex. 1/5) to the beginning of each piece"
        message = self.m + " " + self.b[2]["sig"]
        messagelen = len(message)
        numberofmessages = self.demodulo(messagelen, 144)
        tokenlist = message.split()
        countertoken = 0
        endresultlist = []
        midresultlist = []
        tokenlistlength = len(tokenlist)
        trigger = 1
        triggerdel = 1
        if numberofmessages == 1:
            while trigger:
                counterlength = 0
                while counterlength < 144:
                    if countertoken < tokenlistlength:
                        midresultlist.append(tokenlist[countertoken])
                        if countertoken:
                            counterlength = counterlength + len(tokenlist[countertoken]) + 1
                        else:
                            counterlength = counterlength + len(tokenlist[countertoken])
                        countertoken = countertoken + 1
                    else:
                        trigger = 0
                        triggerdel = 0
                        counterlength = 160
                countertoken = countertoken - 1
                if triggerdel:
                    del midresultlist[-1]
                else:
                    pass
                result = " ".join(midresultlist)
                endresultlist.append(result)
                midresultlist = []
        else:
            messagexof = 1
            while trigger:
                counterlength = 0
                while counterlength < 144:
                    if countertoken < tokenlistlength:
                        midresultlist.append(tokenlist[countertoken])
                        if not countertoken:
                            cnt = str(messagexof)+"/"+str(numberofmessages)+":"
                            counterlength = counterlength + len(tokenlist[countertoken]) + len(cnt) + 1
                            midresultlist.insert(0, cnt)
                            messagexof = messagexof + 1
                        elif not counterlength:
                            cnt = str(messagexof)+"/"+str(numberofmessages)+":"
                            counterlength = counterlength + len(tokenlist[countertoken]) + len(cnt) + 1
                            midresultlist.insert(0, str(messagexof)+"/"+str(numberofmessages)+": ")
                            messagexof = messagexof + 1
                        else:
                            counterlength = counterlength + len(tokenlist[countertoken]) + 1
                        countertoken = countertoken + 1
                    else:
                        trigger = 0
                        triggerdel = 0
                        counterlength = 160
                countertoken = countertoken - 1
                if triggerdel:
                    del midresultlist[-1]
                else:
                    pass
                result = " ".join(midresultlist)
                endresultlist.append(result)
                midresultlist = []
        return endresultlist
                
    def sendsms(self, messages, numbers):
        "This function executes smssend by walking trough all pieces of a message and blocks of recipients"
        messages.reverse()
        for item in messages:
            for block in numbers:
                recipients = []
                for recipient in block:
                    recipients.append(recipient[0])
                length = len(item)
                providerfile = self.b[2]["provider"]
                nums = ";".join(recipients)
                nums = nums.replace("\n", "")
                numsm = nums.replace(";", "\n")
                cmd = "smssend " + providerfile + ' "' + item + '" "' + nums + '"'
                print "Sending:", item, "to\n", numsm
                #print cmd
                os.system(cmd)
                
    def mgenerator(self):
        "You can use mgenerator to test your application. It generates random messages"
        import random
        c = [ "1 ", "aa ", "aa ", "bbb ", "bbb ", "cccc ", "cccc ", "cccc ", "cccc ", "ddddd ", "ddddd ", "ddddd ", "ddddd ", "ddddd ", "eeeeee ", "fsdklfd ", "fdskgjsl ", "dfdgfifid "]
        x = random.choice(c)
        x = len(x)
        y = random.choice(c)
        y = len(y)
        z = x * x * y
        message = ""
        for i in range(z):
            word = random.choice(c)
            message = message + word
        return message
        
    def ismn(self, numberoriginal):
        "ismn makes sure that a phonenumber has the correct format"
        number = numberoriginal.replace(" ", "")
        number = number.replace("  ", "")
        number = number.replace("/", "")
        number = number.replace("'", "")
        number = number.replace("+41", "0")
        number = number.replace("0041", "0")
        number = number.replace("(0)", "")
        try:
            int(number)
            # 078 872 45 48 / +41 78 872 45 48
            if len(number) == 10:
                return number
        except:
            return numberoriginal, False
        
    def demodulo(self, number, x):
        "Demodulo returns the number of pieces that are needed to fit a list or a string of a ceratin length to appropriate pieces"
        rest = number%x
        multiplicator = (number - rest) / x
        if rest:
            return multiplicator + 1
        else:
            return multiplicator
        
class pyss:
    "pyss provides the ui to the processsms class"
    def __init__(self, data):
        "init takes 1 argument: the data-tuple"
        self.data = data
        
    def usage(self):
        "Print usage information"
        print """
    pyss [options]|recipients
    
    [OPTIONS]
    -h|--help      shows this screen
    -s|--setup     setup pyss
    -c|--change    change pyss setup
    -g|--group     manage groups
    -p|--person    manage person
    -C|--clean     delete log
    -l|--log       show log entries
    -i|--import     import pb file
    
    [Example]
    pyss --help         Shows this screen
    pyss                Send short message
    pyss -s             pyss setup
    """
    
    def safe(self):
        "Safe changes that were made in data"
        datafilepath = self.data[2]["confighome"] + "/" + "pyssdata.pik"
        datafile = open(datafilepath, "w")
        pickle.dump(self.data, datafile)
        datafile.close()
        
    def send(self):
        "ui to processsms.sendsms"  
        print "Recipients:"
        recipients = raw_input()
        recipient_list = recipients.split()
        print "Message:"
        message = raw_input()
        sms = processsms(self.data, message, recipient_list)
        finalr = sms.getnumbers()
        finalm = sms.tokenizemessage()
        sms.sendsms(finalm, finalr)
        self.data[3].append((recipient_list, message))
        self.safe()
    
    def setup(self):
        "Creates the setup data needed for pyss"
        print "Doing setup"
        person = {}
        group = {}
        setupdata = {}
        home = raw_input("Please input path to your home (example: /home/linus")
        smssendpath = home + "/.smssend"
        if not os.path.exists(smssendpath):
            os.mkdir(smssendpath, 0644)
        out = 1
        while out:
            m0 = "Input your sendsms setup directory. (default = " + smssendpath + ")"
            d = raw_input("""Input your sendsms setup directory. (default = ~/.smssend)""")
            if d:
                if os.path.exists(d):
                    out = 0
                else:
                    print "Path does not exist. Shall I create:", d
                    print "Default = yes"
                    answer = raw_input()
                    if not answer or answer == "y" or answer == "yes":
                        os.mkdir(d, mode="0644")
                        out = 0
                    else:
                        pass
            else:
                d = smssendpath
                out =  0
        setupdata.update({ "confighome" : d })        
        
        out = 1
        while out: 
            pf = raw_input("Input your provider file. (default = provider.sms)")
            m1 = "Input path to your provider file. (default = " + smssendpath + ")"
            ptpf = raw_input(m1)
            if not pf and not ptpf:
                path = d + "/provider.sms"
                if os.path.exists(path):
                    out = 0
                    print "Provider file set to:", path
                else:
                    print "Error! There is no providerfile! You have to get one for pyss and sendsms to work!"
            elif pf and not ptpf:
                path = d + "/" + pf
                if os.path.exists(path):
                    out = 0
                    print "Provider file set to:", path
                else:
                    print "Error! There is no providerfile! You have to get one for pyss and sendsms to work!"
            elif not pf and ptpf:
                path = ptpf + "/provider.sms"
                if os.path.exists(path):
                    out = 0
                    print "Provider file set to:", path
                else:
                    print "Error! There is no providerfile! You have to get one for pyss and sendsms to work!"
            else:
                path = ptpf + "/" + pf
                if os.path.exists(path):
                    out = 0
                    print "Provider file set to:", path
                else:
                    print "Error! There is no providerfile! You have to get one for pyss and sendsms to work!"
        setupdata.update({ "provider" : path })
        
        out = 1
        while out: 
            pb = raw_input("If you have a phonebook-file (*.pb) please input path:")
            if pb and os.path.exists(pb):
                setupdata.update({ "pb" : pb })
                out = 0
            elif pb and not os.path.exists(pb):
                print "This file does not exist. Please retry or go on."
            else:
                out = 0
        sig = raw_input("Please input a signature (default = no signature:")
        if not sig:
            setupdata.update({ "sig" : "" })
        else:
            print "Set", sig, "as your signature"
            setupdata.update({ "sig" : sig })
        if setupdata.has_key("pb"):
            result = importpb(setupdata["pb"])
            person.update(result)
            del setupdata["pb"]
        else:
            pass
        completedata = (person, group, setupdata, [])
        control = smsutils.manageaccount(completedata)
        print "This are your settings:"
        control.showentry(2)
        q = raw_input("Is this correct? (default = yes)")
        if not q or q == "yes" or q == "y":
            pass
        else:
            changes(completedata)
        safe(completedata)
        
        
    def importpb(self, path):
        "Import pb files from original sms-bash-script by Reto Glauser"
        pb = open(path, "r")
        line = pb.readline()
        book = {}
        while line:
            line = line.replace("\n", "")
            couple = line.split(":")
            print "Set number", couple[1], "to person", couple[0]
            result = raw_input("Default = yes")
            if not result or result == "y" or result == "yes":
                    book.update({ couple[0]:couple[1]})
            else:
                pass
            line = pb.readline()
        return book
            
    def importpb2(self, path):
        "Same as importpb, but used directly from the shell"
        print "Trying to import files with entries like this: person:phonenumber"
        try:

            pb = open(path, "r")
        except:
            print "File not found. Aborting!"
            sys.exit()
        line = pb.readline()
        while line:
            line = line.replace("\n", "")
            couple = line.split(":")
            try:
                test = couple[1]
                print "Set number", couple[1], "to person", couple[0]
                result = raw_input("Default = yes: ")
                if not result or result == "y" or result == "yes":
                    self.data.update({ couple[0]:couple[1]})
                else:
                    pass
            except:
                    print "This file is not in the correct format. Aborting!"
                    sys.exit()
            line = pb.readline()
        pb.close()
            
    def changes(self):
        "Change setup"
        print "These are your settings.:"
        control = smsutils.manageaccount(self.data)
        control.showentry(2)
        c = raw_input("Press [Enter] to exit\nInput the setting you want to change:\n")
        if not c:
            pass
        else:
            if self.data[2].has_key(c):
                print "Enter new value for", c
                new = raw_input()
                self.data[2].changeentry(c, new)
            else:
                print "This setting does not exist!"
                changes()
        self.safe()
    
    def managegroup(self):
        "Manage your groups"
        print "These are your groups:"
        control = manageaccount(self.data)
        if self.data[1]:
            control.showentry(1)
        else:
            print "No groups available"
        c = raw_input("Press [Enter] to exit:\nInput the group you want to change:\nInput a new group name to create a new entry:\n\n")
        if not c:
            sys.exit()
        else:
            if self.data[1].has_key(c):
                print "Enter new value for", c
                new = raw_input()
                control.changeentry(c, new, 1)
            else:
                print "Creating new group", c
                members = raw_input("Please input members of the group separated by a blank space:")
                memberlist = members.split()
                control.addentry(c, memberlist, 1)
        self.safe()
        self.managegroup()
        
    def manageperson(self):
        "Manage your persons"
        print "These are the persons in your phonebook:"
        control = manageaccount(self.data)
        if self.data[0]:
            control.showentry(0)
        else:
            print "No persons available"
        c = raw_input("Press [Enter] to exit:\nInput the person you want to change:\nInput a new person to create a new entry:\n\n")
        if not c:
            sys.exit()
        else:
            if self.data[0].has_key(c):
                print "Enter new value for", c
                new = raw_input()
                control.changeentry(c, new, 0)
            else:
                print "Creating new person", c
                number = raw_input("Please input number of the person:")
                control.addentry(c, number, 0)
        self.safe()
        self.manageperson()
        
    def clean(self):
        "clean log"
        self.data = (self.data[0], self.data[1], self.data[2], [])
        self.safe()
        
    def logwrite(self):
        "Show loginfo"
        if not self.data[3]:
            print "No log entries"
        else:
            for item in self.data[3]:
                print "Wrote:"
                print item[1]
                print "to", " ".join(item[0])    
    
def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hscgpCli:", ["help", "setup", "change", "group", "person", "clean", "log", "import="])
    except getopt.GetoptError:
        usage()
        sys.exit(2)
    try:
        datafile = open( "/home/william/.smssend/pyssdata.pik", "r" )
        data = pickle.load(datafile)
        datafile.close()
        
    except:
        print "No config-file found! Performing setup"
        ui = pyss({})
        ui.setup()
        sys.exit()
    if not opts:
        sms = pyss(data)
        sms.send()
    else:
        ui = pyss(data)
        for o, a in opts:
            if o in ("-h", "--help"):
                ui.usage()
                sys.exit()
            elif o in ("-s", "--setup"):
                ui.setup()
                sys.exit()
            elif o in ("-c", "--change"):
                ui.change()
                sys.exit()
            elif o in ("-g", "--group"):
                ui.managegroup()
                sys.exit()
            elif o in ("-p", "--person"):
                ui.manageperson()
                sys.exit()
            elif o in ("-C", "--clean"):
                ui.clean()
                sys.exit()
            elif o in ("-l", "--log"):
                ui.logwrite()
                sys.exit()
            elif o in ("-i", "--import"):
                print a
                ui.importpb2(a)
                sys.exit()
            else:
                pass
            
            
main()
Zugegeben, das Ganze hat noch ein paar Makel, Design-Fehler etc. Aber es ist soweit ganz brauchbar und neuere Versionen sollten diese auch ausbessern...

Gruss

Clython
Antworten