captain_perreiro

Untitled

Oct 2nd, 2013
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.14 KB | None | 0 0
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. # https://github.com/asterisk/starpy/blob/master/examples/amicommand.py
  4. # https://github.com/asterisk/starpy/blob/master/starpy/manager.py
  5. # http://olihb.com/2010/08/08/incoming-call-popup-under-ubuntu-and-asterisk/
  6. # http://www.oak-wood.co.uk/oss/callpoppy
  7. import MySQLdb
  8. import string
  9. import datetime
  10. from Daemon import Daemon
  11. import sys
  12. import urllib
  13. import simplejson
  14. import lxml.html
  15. import random
  16. from twisted.internet import gtk2reactor
  17. gtk2reactor.install(True)
  18. from twisted.internet import reactor
  19. import pynotify
  20. from starpy.manager import AMIFactory
  21. from twisted.internet import task
  22. from twisted.application.service import Application
  23. import logging,gnome.ui,sys
  24.  
  25. #asterisk AMI login
  26. server="192.168.0.1"
  27. port=5038
  28. username="user"
  29. secret="password"
  30. extensions={"SIP/770":"First Phone",
  31. "SIP/780":"Second Phone"}
  32. context=["TTK",]
  33. log = logging.getLogger("pyCalledMe2")
  34.  
  35. timeouttask=None
  36. timeoutping=5
  37. timeoutloop=120
  38. # Клас для демонизации скрипта
  39. class MyDaemon(Daemon):
  40. def run(self):
  41. while True:
  42. #manager.log.setLevel( logging.DEBUG )
  43. #log.setLevel(logging.INFO)
  44. logging.basicConfig()
  45.  
  46. #exit script when gnome logs out
  47. gnome.program_init ("pyCalledMe", "1.0")
  48. client = gnome.ui.master_client()
  49. client.connect("save-yourself", killapp)
  50.  
  51. #init libnotifier and reactor
  52. pynotify.init("pyCalledMe");
  53. reactor.callWhenRunning(main)
  54. reactor.run()
  55. # Клас для получение имени контагента по телефонному номеру
  56. class calloutrec:
  57. DBHOST = "192.168.0.1"
  58. DBUSER = "voip"
  59. DBPASS = "voip"
  60. DBNAME = "voip"
  61. GISKEY = ['key1', 'key2']
  62.  
  63. def db_init(self):
  64. """ Функция соединения с БД """
  65. connect = MySQLdb.connect(db=self.DBNAME, host=self.DBHOST, user=self.DBUSER, passwd=self.DBPASS, use_unicode=True, charset="utf8")
  66. connect.set_character_set('utf8')
  67. return connect
  68.  
  69. def rosfirm(self,num):
  70. """ Функция парсинга ответа от www.rosfirm.ru,получения названия контрагента возвращает список вида ['Название контрагента','Префиск организации' ] """
  71. headers = {'User-Agent' : 'Mozilla/22.0 (compatible; MSIE 7.0; Windows NT 6.0)'}
  72. # ссылка для получения названия организации
  73. list = []
  74. 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)
  75. doc = lxml.html.fromstring(page.read())
  76. txt = doc.xpath('//div[@class="goodsDescription"]/h3/a/text()')
  77. if len(txt) == 0:
  78. return list
  79. # Преобразуем массив в строку
  80. x = ''.join(txt[0]).encode("utf-8").strip()
  81. if x.find(',') == -1:
  82. begin = x.find('(')
  83. end = x.find(')')
  84. srez = x[begin + 1:end]
  85. if srez.find('"') > 0:
  86. y = srez.split(' ')[0].replace('компания ','').replace('Компания ','').replace('"','').strip() # Название Организации
  87. z = srez[srez.find('"') + 1:srez.rfind('"')] # Префикс организации (ЗАО,ООО..)
  88. list.append(y) #вынести в отдельную функцию!
  89. list.append(z)
  90. return list
  91. y = srez.split(' ')[0].replace('компания ','').replace('Компания ','').replace('"','').strip() # Название Организации
  92. z = srez.split(' ')[1].strip() # Префикс организации (ЗАО,ООО..)
  93. list.append(y)
  94. list.append(z)
  95. return list
  96. y = x.split(',')[-1].strip() # Название Организации
  97. z = x.split(',')[-2].replace('компания ','').replace('Компания ','').replace('"','').strip() # Префикс организации (ЗАО,ООО..)
  98. list.append(y)
  99. list.append(z)
  100. return list
  101.  
  102. def togis(self,num):
  103. """ Запрос названия организациия из базы 2gis """
  104. list = []
  105. rand_key = random.choice(self,GISKEY)
  106. 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: 'Миасс'}
  107. if len(num) < 8 : num = "351"+num
  108. if int(num[0:5]) in dic_city:
  109. city=dic_city[int(num[0:5])]
  110. else:
  111. if int(num[0:4]) in dic_city:
  112. city=dic_city[int(num[0:4])]
  113. else:
  114. if int(num[0:3]) in dic_city:
  115. city=dic_city[int(num[0:3])]
  116. num=int(num)
  117. else: return list
  118. 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)
  119. result = simplejson.load(urllib.urlopen(query_url))
  120. if result.has_key('result'):
  121. x = result['result'][0]['name'].strip()
  122. y = result['result'][0]['name'].split(',')
  123. if len(y) > 3:
  124. y = x.split(',')[0].strip() # название организации
  125. z = x.split(',')[1].strip() # префикс организации
  126. h = x.split(',')[2].strip() # описание организации
  127. list.append(y)
  128. list.append(z)
  129. list.append(h)
  130. else:
  131. y = x.split(',')[0].strip()
  132. h = x.split(',')[1].strip()
  133. list.append(h)
  134. list.append(y)
  135. return list
  136.  
  137. def togis_write(self,num,z):
  138. """ Функция записи ответа от 2gis """
  139. dt = datetime.date.today()
  140. cursor = self.db_init().cursor()
  141. y = self.togis(num)
  142. if (z == 1) and (len(y) == 0):
  143. return num
  144. if z == 1:
  145. cursor.execute("""UPDATE name SET organization = %s, date = %s, prefix = %s WHERE number = %s""",(y[1], dt, y[0], int(num)))
  146. return y[1]
  147. if len(y) == 0:
  148. cursor.execute("""INSERT INTO name(organization, number, date, source, prefix) values(%s,%s,%s,%s,%s)""",('none', int(num), dt, 0,'none'))
  149. x = 'none'
  150. else:
  151. cursor.execute("""INSERT INTO name(organization, number, date, source, prefix) values(%s,%s,%s,%s,%s)""",(y[1], int(num), dt, 0, y[0]))
  152. x = y[1] # маркер не пустого значения
  153. return x
  154.  
  155. def rosfirm_write(self,num,z):
  156. """ Функция записи ответа от rosfirm """
  157. dt = datetime.date.today()
  158. cursor = self.db_init().cursor()
  159. y = self.rosfirm(num)
  160. if (z == 1) and (len(y) == 0):
  161. return num
  162. if z == 1:
  163. cursor.execute("""UPDATE name SET organization = %s, date = %s, prefix = %s WHERE number = %s""",(y[1], dt, y[0], int(num)))
  164. return y[1]
  165. if len(y) == 0:
  166. cursor.execute("""INSERT INTO name(organization, number, date, source, prefix) values(%s,%s,%s,%s,%s)""",('none', int(num), dt, 1,'none'))
  167. x = 'none'
  168. else:
  169. cursor.execute("""INSERT INTO name(organization, number, date, source, prefix) values(%s,%s,%s,%s,%s)""",(y[1], int(num), dt, 1, y[0]))
  170. x = y[1]
  171. return x
  172.  
  173. def getCallername(self,num):
  174. """ Основная функция которая сначала анализирует и запрашивает данные в зависимости от номера """
  175. # Соединение с базой и получение название контагента
  176. cursor = self,db_init().cursor()
  177. cursor.execute("""SELECT organization,date,source,prefix FROM name WHERE number=%s LIMIT 1""", int(num,))
  178. if cursor.fetchone() != None:
  179. for row in cursor:
  180. x = row[0]
  181. y = row[1]
  182. z = row[2]
  183. h = row[3]
  184. y = datetime.date.today() - y
  185. if (x == 'none') and (y < datetime.timedelta(days=60)): # Проверяем номер в базе, чтобы постоянно не кидать запросы к web
  186. self.db_init().close()
  187. return num
  188. if (y > datetime.timedelta(days=60)) and (z == 1) and (x != 'none'): # Проверяем что дата не устарела для rosfirm
  189. x = self.rosfirm_write(num,1) # Запрос на обновление информации
  190. if (y > datetime.timedelta(days=60)) and (z == 0) and (x != 'none'): # Проверяем что дата не устарела для 2GIS
  191. x = self.togis_write(num,1)
  192. else:
  193. x = self.togis_write(num,0) # Записи в базу,определение номера через 2gis!
  194. if (x == 'none'): x = self.rosfirm_write(num,1) # Записи в базу,определение номера через rosfirm!
  195. if (x == 'none'):
  196. x = num # Возвращаем номер чтобы не приходило значение none
  197. return x
  198. self.db_init().close()
  199. if (x == 'none'): return num
  200. if ('h' in locals()) and (x != 'none'): c = h + " " + '"' + x + '"'
  201. else: return x
  202. if len(c) > 15: x = x
  203. else: x = c
  204. return x # Возвращаем наименование организации и префикс,но не более 15 символов для yealink T22
  205.  
  206. # Клас подключения к AMI
  207. class callMeFactory(AMIFactory):
  208. cbconnect=None
  209. def __init__(self):
  210. AMIFactory.__init__(self, username, secret)
  211. def connect(self):
  212. df = self.login(server, port)
  213. if self.cbconnect!=None:
  214. df.addCallback(self.cbconnect)
  215. def clientConnectionLost(self,connector,reason):
  216. log.info("connection lost - connecting again")
  217. reactor.callLater(1,self.connect)
  218. def clientConnectionFailed(self,connector,reason):
  219. log.info("connection failed - connecting again")
  220. reactor.callLater(1,self.connect)
  221. # Клас для полчение имени контагента по телефонному номеру
  222. class cdrbase:
  223. DBHOST = "192.168.0.1"
  224. DBUSER = "asterisk"
  225. DBPASS = "pasword"
  226. DBNAME = "asterisk"
  227.  
  228. def db_init(self):
  229. """ Функция соединения с БД """
  230. connect = MySQLdb.connect(db=self.DBNAME, host=self.DBHOST, user=self.DBUSER, passwd=self.DBPASS, use_unicode=True, charset="utf8")
  231. connect.set_character_set('utf8')
  232. return connect
  233.  
  234. def cdr(self,num):
  235. """ Функция поиска по cdr базе в asterisk """
  236. d = datetime.date.today()
  237. date_start = d.strftime("%Y-%m-%d %H:%M:%S")
  238. date_end = d.strftime("%Y-%m-%d 23:59:59")
  239. cursor = self.db_init().cursor()
  240. if (num[0:4] == '3512') or (num[0:4] == '3517'):
  241. num = str(num[3:])
  242. num9 = '9' + num
  243. 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))
  244. else:
  245. #num = '8' + num
  246. #num9 = '9' + num
  247. num9 = num
  248. 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))
  249. if (cursor.fetchone() != None):
  250. for row in cursor:
  251. x = row[0]
  252. else: x='none'
  253. if len(x) < 2: x='none'
  254. self.db_init().close()
  255. return x
  256.  
  257. def onDial(protocol,event):
  258. """ Функция слушат определенные номера из переменной extensions и при звонке на них выполняет действия... """
  259. if 'destination' in event:
  260. destination=event['destination']
  261. for s in extensions.keys():
  262. if destination.startswith(s):
  263. cid=event['calleridnum']
  264. cidname=event['calleridname']
  265. channel=event['channel']
  266. extname=extensions[s]
  267. if (cidname == "Пономарев"):
  268. # protocol.setVar(channel, "uniqueid", "test")
  269. print(protocol.getVar(channel,'channel'))
  270. n=pynotify.Notification("Incoming call for "+extname,cidname+"\n"+cid,"call-start")
  271. print "calleridnum-"+cid
  272. print "calleridname-"+cidname
  273. auto = cdrbase()
  274. if (auto.cdr(cid) != "none"): print auto.cdr(cid)
  275. n.show()
  276.  
  277. def onCall(protocol,event):
  278. """ Функция при создании нового вызова,проверяет исходящий ли это по переменной contex и запрашивает из 2gis и росфирм имя звонящего """
  279. if 'context' in event:
  280. incoming=event['context']
  281. for element in context:
  282. if incoming.startswith(element):
  283. cid=event['calleridnum']
  284. if len(cid) > 5:
  285. name = calloutrec()
  286. print name.getCallername(cid)
  287.  
  288. def checknetlink(protocol):
  289.  
  290. def ontimeout():
  291. log.info("timeout")
  292. if dc.active():
  293. dc.cancel()
  294. timeouttask.stop()
  295. protocol.transport.loseConnection()
  296.  
  297. def canceltimeout(*val):
  298. if dc.active():
  299. dc.cancel()
  300.  
  301. log.info("cancel timeout")
  302. log.info(val)
  303.  
  304. def success(val):
  305. pass
  306.  
  307. log.info("setting timeout")
  308. dc = reactor.callLater(timeoutping,ontimeout)
  309. df = protocol.ping()
  310. df.addBoth(canceltimeout)
  311. df.addCallback(success)
  312. df.addErrback(ontimeout)
  313.  
  314. def onLogin(protocol):
  315. """ Функция вызывает callback функции в зависимости от того какое событие приходит через ami """
  316. df = protocol.registerEvent("Dial",onDial)
  317. ds = protocol.registerEvent("Newchannel",onCall)
  318. global timeouttask
  319. timeouttask = task.LoopingCall(checknetlink,protocol)
  320. timeouttask.start(timeoutloop);
  321. return df,ds # наверное не нужно
  322.  
  323. def main():
  324. cm = callMeFactory()
  325. cm.cbconnect=onLogin
  326. cm.connect()
  327.  
  328. def killapp(*args): # скорее всего не нужно убрать
  329. reactor.stop()
  330. return True
  331.  
  332. if __name__ == '__main__':
  333. # daemon = MyDaemon('/tmp/pyami.pid')
  334. # if len(sys.argv) == 2:
  335. # if 'start' == sys.argv[1]:
  336. # daemon.start()
  337. # elif 'stop' == sys.argv[1]:
  338. # daemon.stop()
  339. # elif 'restart' == sys.argv[1]:
  340. # daemon.restart()
  341. # elif 'status' == sys.argv[1]:
  342. # daemon.status()
  343. # else:
  344. # print "Unknown command"
  345. # print "usage: start|stop|restart"
  346. # sys.exit(2)
  347. # sys.exit(0)
  348. # else:
  349. # print "usage: start|stop|restart"
  350. # sys.exit(2)
  351. logging.basicConfig()
  352.  
  353. #exit script when gnome logs out
  354. gnome.program_init ("pyCalledMe", "1.0")
  355. client = gnome.ui.master_client()
  356. client.connect("save-yourself", killapp)
  357. #init libnotifier and reactor
  358. pynotify.init("pyCalledMe");
  359. reactor.callWhenRunning(main)
  360. reactor.run()
Advertisement
Add Comment
Please, Sign In to add comment