Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- # https://github.com/asterisk/starpy/blob/master/examples/amicommand.py
- # https://github.com/asterisk/starpy/blob/master/starpy/manager.py
- # http://olihb.com/2010/08/08/incoming-call-popup-under-ubuntu-and-asterisk/
- # http://www.oak-wood.co.uk/oss/callpoppy
- import MySQLdb
- import string
- import datetime
- from Daemon import Daemon
- import sys
- import urllib
- import simplejson
- import lxml.html
- import random
- from twisted.internet import gtk2reactor
- gtk2reactor.install(True)
- from twisted.internet import reactor
- import pynotify
- from starpy.manager import AMIFactory
- from twisted.internet import task
- from twisted.application.service import Application
- import logging,gnome.ui,sys
- #asterisk AMI login
- server="192.168.0.1"
- port=5038
- username="user"
- secret="password"
- extensions={"SIP/770":"First Phone",
- "SIP/780":"Second Phone"}
- context=["TTK",]
- log = logging.getLogger("pyCalledMe2")
- timeouttask=None
- timeoutping=5
- timeoutloop=120
- # Клас для демонизации скрипта
- class MyDaemon(Daemon):
- def run(self):
- while True:
- #manager.log.setLevel( logging.DEBUG )
- #log.setLevel(logging.INFO)
- logging.basicConfig()
- #exit script when gnome logs out
- gnome.program_init ("pyCalledMe", "1.0")
- client = gnome.ui.master_client()
- client.connect("save-yourself", killapp)
- #init libnotifier and reactor
- pynotify.init("pyCalledMe");
- reactor.callWhenRunning(main)
- reactor.run()
- # Клас для получение имени контагента по телефонному номеру
- class calloutrec:
- DBHOST = "192.168.0.1"
- DBUSER = "voip"
- DBPASS = "voip"
- DBNAME = "voip"
- GISKEY = ['key1', 'key2']
- def db_init(self):
- """ Функция соединения с БД """
- connect = MySQLdb.connect(db=self.DBNAME, host=self.DBHOST, user=self.DBUSER, passwd=self.DBPASS, use_unicode=True, charset="utf8")
- connect.set_character_set('utf8')
- return connect
- def rosfirm(self,num):
- """ Функция парсинга ответа от www.rosfirm.ru,получения названия контрагента возвращает список вида ['Название контрагента','Префиск организации' ] """
- headers = {'User-Agent' : 'Mozilla/22.0 (compatible; MSIE 7.0; Windows NT 6.0)'}
- # ссылка для получения названия организации
- list = []
- page = urllib.urlopen("http://www.rosfirm.ru/catalog?show_list=1&se=1&field_keywords=&field_search_type=&field_phone="+num +"&field_director=&srubrik=&rubrik_id=&sel_rubrik_path=&save_rubrik_flag=1&search=1&reset_reset=1", None, headers)
- doc = lxml.html.fromstring(page.read())
- txt = doc.xpath('//div[@class="goodsDescription"]/h3/a/text()')
- if len(txt) == 0:
- return list
- # Преобразуем массив в строку
- x = ''.join(txt[0]).encode("utf-8").strip()
- if x.find(',') == -1:
- begin = x.find('(')
- end = x.find(')')
- srez = x[begin + 1:end]
- if srez.find('"') > 0:
- y = srez.split(' ')[0].replace('компания ','').replace('Компания ','').replace('"','').strip() # Название Организации
- z = srez[srez.find('"') + 1:srez.rfind('"')] # Префикс организации (ЗАО,ООО..)
- list.append(y) #вынести в отдельную функцию!
- list.append(z)
- return list
- y = srez.split(' ')[0].replace('компания ','').replace('Компания ','').replace('"','').strip() # Название Организации
- z = srez.split(' ')[1].strip() # Префикс организации (ЗАО,ООО..)
- list.append(y)
- list.append(z)
- return list
- y = x.split(',')[-1].strip() # Название Организации
- z = x.split(',')[-2].replace('компания ','').replace('Компания ','').replace('"','').strip() # Префикс организации (ЗАО,ООО..)
- list.append(y)
- list.append(z)
- return list
- def togis(self,num):
- """ Запрос названия организациия из базы 2gis """
- list = []
- rand_key = random.choice(self,GISKEY)
- dic_city = {39022: 'Абакан', 8182: 'Архангельск', 8512: 'Астрахань', 3852: 'Барнаул', 4722: 'Белгород', 3854: 'Бийск', 4162: 'Благовещенск', 3953: 'Братск', 4832: 'Брянск', 8162: 'Великий Новгород', 4232: 'Владивосток', 4922: 'Владимир', 8442: 'Волгоград', 8172: 'Вологда', 4732: 'Воронеж', 38822: 'Горный Алтай', 343: 'Екатеринбург', 493: 'Иваново', 3412: 'Ижевск', 3952: 'Иркутск', 8362: 'Йошкар-Ола', 843: 'Казань', 4012: 'Калининград', 4842: 'Калуга', 3842: 'Кемерово', 8332: 'Киров', 4942: 'Кострома', 861: 'Краснодар', 3912: 'Красноярск', 3522: 'Курган', 4712: 'Курск', 4742: 'Липецк', 3519: 'Магнитогорск', 8552: 'Набережные Челны', 3466: 'Нижневартовск', 8312: 'Нижний Новгород', 3435: 'Нижний Тагил', 3843: 'Новокузнецк', 8617: 'Новороссийск', 3812: 'Омск', 3532: 'Оренбург', 8412: 'Пенза', 3422: 'Пермь', 863: 'Ростов на Дону', 4912: 'Рязань', 846: 'Самара', 812: 'Санкт-Петербург', 8452: 'Саратов', 4812: 'Смоленск', 8622: 'Сочи', 8652: 'Ставрополь', 4725: 'Старый Оскол', 3473: 'Стерлитамак', 3462: 'Сургут', 8212: 'Сыктывкар', 4822: 'Тверь', 8482: 'Тольяти', 3822: 'Томск', 4872: 'Тула', 3452: 'Тюмень', 3012: 'Улан-Удэ', 8422: 'Ульяновск', 3472: 'Уфа', 4212: 'Хабаровск', 351: 'Челябинск', 3022: 'Чита', 4112: 'Якутск', 4852: 'Ярославль', 499: 'Москва', 495: 'Москва', 3513: 'Миасс'}
- if len(num) < 8 : num = "351"+num
- if int(num[0:5]) in dic_city:
- city=dic_city[int(num[0:5])]
- else:
- if int(num[0:4]) in dic_city:
- city=dic_city[int(num[0:4])]
- else:
- if int(num[0:3]) in dic_city:
- city=dic_city[int(num[0:3])]
- num=int(num)
- else: return list
- query_url = ("http://catalog.api.2gis.ru/search?what={0}&version=1.3&where=%s&pagesize=5&key=%s&lang=ru").format(num)% (city, rand_key)
- result = simplejson.load(urllib.urlopen(query_url))
- if result.has_key('result'):
- x = result['result'][0]['name'].strip()
- y = result['result'][0]['name'].split(',')
- if len(y) > 3:
- y = x.split(',')[0].strip() # название организации
- z = x.split(',')[1].strip() # префикс организации
- h = x.split(',')[2].strip() # описание организации
- list.append(y)
- list.append(z)
- list.append(h)
- else:
- y = x.split(',')[0].strip()
- h = x.split(',')[1].strip()
- list.append(h)
- list.append(y)
- return list
- def togis_write(self,num,z):
- """ Функция записи ответа от 2gis """
- dt = datetime.date.today()
- cursor = self.db_init().cursor()
- y = self.togis(num)
- if (z == 1) and (len(y) == 0):
- return num
- if z == 1:
- cursor.execute("""UPDATE name SET organization = %s, date = %s, prefix = %s WHERE number = %s""",(y[1], dt, y[0], int(num)))
- return y[1]
- if len(y) == 0:
- cursor.execute("""INSERT INTO name(organization, number, date, source, prefix) values(%s,%s,%s,%s,%s)""",('none', int(num), dt, 0,'none'))
- x = 'none'
- else:
- cursor.execute("""INSERT INTO name(organization, number, date, source, prefix) values(%s,%s,%s,%s,%s)""",(y[1], int(num), dt, 0, y[0]))
- x = y[1] # маркер не пустого значения
- return x
- def rosfirm_write(self,num,z):
- """ Функция записи ответа от rosfirm """
- dt = datetime.date.today()
- cursor = self.db_init().cursor()
- y = self.rosfirm(num)
- if (z == 1) and (len(y) == 0):
- return num
- if z == 1:
- cursor.execute("""UPDATE name SET organization = %s, date = %s, prefix = %s WHERE number = %s""",(y[1], dt, y[0], int(num)))
- return y[1]
- if len(y) == 0:
- cursor.execute("""INSERT INTO name(organization, number, date, source, prefix) values(%s,%s,%s,%s,%s)""",('none', int(num), dt, 1,'none'))
- x = 'none'
- else:
- cursor.execute("""INSERT INTO name(organization, number, date, source, prefix) values(%s,%s,%s,%s,%s)""",(y[1], int(num), dt, 1, y[0]))
- x = y[1]
- return x
- def getCallername(self,num):
- """ Основная функция которая сначала анализирует и запрашивает данные в зависимости от номера """
- # Соединение с базой и получение название контагента
- cursor = self,db_init().cursor()
- cursor.execute("""SELECT organization,date,source,prefix FROM name WHERE number=%s LIMIT 1""", int(num,))
- if cursor.fetchone() != None:
- for row in cursor:
- x = row[0]
- y = row[1]
- z = row[2]
- h = row[3]
- y = datetime.date.today() - y
- if (x == 'none') and (y < datetime.timedelta(days=60)): # Проверяем номер в базе, чтобы постоянно не кидать запросы к web
- self.db_init().close()
- return num
- if (y > datetime.timedelta(days=60)) and (z == 1) and (x != 'none'): # Проверяем что дата не устарела для rosfirm
- x = self.rosfirm_write(num,1) # Запрос на обновление информации
- if (y > datetime.timedelta(days=60)) and (z == 0) and (x != 'none'): # Проверяем что дата не устарела для 2GIS
- x = self.togis_write(num,1)
- else:
- x = self.togis_write(num,0) # Записи в базу,определение номера через 2gis!
- if (x == 'none'): x = self.rosfirm_write(num,1) # Записи в базу,определение номера через rosfirm!
- if (x == 'none'):
- x = num # Возвращаем номер чтобы не приходило значение none
- return x
- self.db_init().close()
- if (x == 'none'): return num
- if ('h' in locals()) and (x != 'none'): c = h + " " + '"' + x + '"'
- else: return x
- if len(c) > 15: x = x
- else: x = c
- return x # Возвращаем наименование организации и префикс,но не более 15 символов для yealink T22
- # Клас подключения к AMI
- class callMeFactory(AMIFactory):
- cbconnect=None
- def __init__(self):
- AMIFactory.__init__(self, username, secret)
- def connect(self):
- df = self.login(server, port)
- if self.cbconnect!=None:
- df.addCallback(self.cbconnect)
- def clientConnectionLost(self,connector,reason):
- log.info("connection lost - connecting again")
- reactor.callLater(1,self.connect)
- def clientConnectionFailed(self,connector,reason):
- log.info("connection failed - connecting again")
- reactor.callLater(1,self.connect)
- # Клас для полчение имени контагента по телефонному номеру
- class cdrbase:
- DBHOST = "192.168.0.1"
- DBUSER = "asterisk"
- DBPASS = "pasword"
- DBNAME = "asterisk"
- def db_init(self):
- """ Функция соединения с БД """
- connect = MySQLdb.connect(db=self.DBNAME, host=self.DBHOST, user=self.DBUSER, passwd=self.DBPASS, use_unicode=True, charset="utf8")
- connect.set_character_set('utf8')
- return connect
- def cdr(self,num):
- """ Функция поиска по cdr базе в asterisk """
- d = datetime.date.today()
- date_start = d.strftime("%Y-%m-%d %H:%M:%S")
- date_end = d.strftime("%Y-%m-%d 23:59:59")
- cursor = self.db_init().cursor()
- if (num[0:4] == '3512') or (num[0:4] == '3517'):
- num = str(num[3:])
- num9 = '9' + num
- cursor.execute("""SELECT src FROM cdr WHERE calldate>=(%s) AND calldate<=(%s) AND (dst=(%s) OR dst=(%s)) ORDER BY calldate ASC LIMIT 1""",( date_start, date_end, num, num9))
- else:
- #num = '8' + num
- #num9 = '9' + num
- num9 = num
- cursor.execute("""SELECT src FROM cdr WHERE calldate>=(%s) AND calldate<=(%s) AND (dst=(%s) OR dst=(%s)) ORDER BY calldate ASC LIMIT 1""",( date_start, date_end, num, num9))
- if (cursor.fetchone() != None):
- for row in cursor:
- x = row[0]
- else: x='none'
- if len(x) < 2: x='none'
- self.db_init().close()
- return x
- def onDial(protocol,event):
- """ Функция слушат определенные номера из переменной extensions и при звонке на них выполняет действия... """
- if 'destination' in event:
- destination=event['destination']
- for s in extensions.keys():
- if destination.startswith(s):
- cid=event['calleridnum']
- cidname=event['calleridname']
- channel=event['channel']
- extname=extensions[s]
- if (cidname == "Пономарев"):
- # protocol.setVar(channel, "uniqueid", "test")
- print(protocol.getVar(channel,'channel'))
- n=pynotify.Notification("Incoming call for "+extname,cidname+"\n"+cid,"call-start")
- print "calleridnum-"+cid
- print "calleridname-"+cidname
- auto = cdrbase()
- if (auto.cdr(cid) != "none"): print auto.cdr(cid)
- n.show()
- def onCall(protocol,event):
- """ Функция при создании нового вызова,проверяет исходящий ли это по переменной contex и запрашивает из 2gis и росфирм имя звонящего """
- if 'context' in event:
- incoming=event['context']
- for element in context:
- if incoming.startswith(element):
- cid=event['calleridnum']
- if len(cid) > 5:
- name = calloutrec()
- print name.getCallername(cid)
- def checknetlink(protocol):
- def ontimeout():
- log.info("timeout")
- if dc.active():
- dc.cancel()
- timeouttask.stop()
- protocol.transport.loseConnection()
- def canceltimeout(*val):
- if dc.active():
- dc.cancel()
- log.info("cancel timeout")
- log.info(val)
- def success(val):
- pass
- log.info("setting timeout")
- dc = reactor.callLater(timeoutping,ontimeout)
- df = protocol.ping()
- df.addBoth(canceltimeout)
- df.addCallback(success)
- df.addErrback(ontimeout)
- def onLogin(protocol):
- """ Функция вызывает callback функции в зависимости от того какое событие приходит через ami """
- df = protocol.registerEvent("Dial",onDial)
- ds = protocol.registerEvent("Newchannel",onCall)
- global timeouttask
- timeouttask = task.LoopingCall(checknetlink,protocol)
- timeouttask.start(timeoutloop);
- return df,ds # наверное не нужно
- def main():
- cm = callMeFactory()
- cm.cbconnect=onLogin
- cm.connect()
- def killapp(*args): # скорее всего не нужно убрать
- reactor.stop()
- return True
- if __name__ == '__main__':
- # daemon = MyDaemon('/tmp/pyami.pid')
- # if len(sys.argv) == 2:
- # if 'start' == sys.argv[1]:
- # daemon.start()
- # elif 'stop' == sys.argv[1]:
- # daemon.stop()
- # elif 'restart' == sys.argv[1]:
- # daemon.restart()
- # elif 'status' == sys.argv[1]:
- # daemon.status()
- # else:
- # print "Unknown command"
- # print "usage: start|stop|restart"
- # sys.exit(2)
- # sys.exit(0)
- # else:
- # print "usage: start|stop|restart"
- # sys.exit(2)
- logging.basicConfig()
- #exit script when gnome logs out
- gnome.program_init ("pyCalledMe", "1.0")
- client = gnome.ui.master_client()
- client.connect("save-yourself", killapp)
- #init libnotifier and reactor
- pynotify.init("pyCalledMe");
- reactor.callWhenRunning(main)
- reactor.run()
Advertisement
Add Comment
Please, Sign In to add comment