четверг, 19 марта 2015 г.

Сохраняем телефонные разговоры asterisk

[default-ololo]
exten => _X.,1,Set(dirname="/var/www/asterisk/mp3/${STRFTIME(${EPOCH},,%d_%m_%Y)}")
SIPCALLID=${SIPCALLID}" >> /tmp/1111.txt)
exten => _X.,n,Set(fname="${STRFTIME(${EPOCH},,%d_%m_%Y_%H:%M)}-${CALLERID(num)}-${EXTEN}")
exten => _X.,n,Set(monopt= nice -n 14 /usr/bin/lame -b 16 --silent "/tmp/wav/${fname}.wav" "${dirname}/${fname}.mp3" && chmod o+r,g+r "${dirname}/${fname}.mp
exten => _X.,n,MixMonitor(/tmp/wav/${fname}.wav,b,${monopt})
exten => _X.,n,Dial(SIP/avaya/${EXTEN})
exten => _X.,n,Hangup()



четверг, 26 февраля 2015 г.

Забираем по фтп файлы *.bak
python3

import ftplib,sys

def getbinary(ftp, filename, outfile):
   try:
      print("retrieving file "+filename+' to -> '+outfile+"...")
      fout=open(outfile,'wb')
      ftp.retrbinary("RETR " + filename, fout.write)
      fout.close()
   except:
      print("somthing wrong! error")
      sys.exit(2)

def getpastfilenamofdir(ftp, dir):
    ftp.cwd(dir)
    pastfilename=ftp.nlst('*.bak')[-1:][0]
    getbinary(ftp, pastfilename, pastfilename)

ftp=ftplib.FTP('10.10.10.10')
ftp.login('user','password')

getpastfilenamofdir(ftp, 'folder1')
getpastfilenamofdir(ftp, '../folder2/folder3')
getpastfilenamofdir(ftp, '../../folder4')
ftp.close()

sys.exit(0)

воскресенье, 1 февраля 2015 г.

Пишем штуку для отправки файла в некую компанию. С авторизацией и конфигом ;)
Все оригинальные имена email,файлов/URLов похерены.
Используется изнутри 1С для отправки сформированного csv файла.

# -*- coding: utf8 -*-
# alex~~~@zztop.ru, 2015

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import sys,codecs
from os.path import isfile
import ConfigParser

#http://habrahabr.ru/post/117236/
def setup_console(sys_enc="utf-8"):
    reload(sys)
    try:
        if sys.platform.startswith("win"):
            import ctypes
            enc = "cp%d" % ctypes.windll.kernel32.GetOEMCP()
        else:
            enc = (sys.stdout.encoding if sys.stdout.isatty() else
                        sys.stderr.encoding if sys.stderr.isatty() else
                            sys.getfilesystemencoding() or sys_enc)

        sys.setdefaultencoding(sys_enc)

        if sys.stdout.isatty() and sys.stdout.encoding != enc:
            sys.stdout = codecs.getwriter(enc)(sys.stdout, 'replace')

        if sys.stderr.isatty() and sys.stderr.encoding != enc:
            sys.stderr = codecs.getwriter(enc)(sys.stderr, 'replace')

    except:
        pass

def recreateconf():
   try:
      f1=open('ololo.conf','w')
      f1.write("[MAIN]\nURL=http://parts.bmw.ru\nLOGIN=qwerty@mail.ru\nPASSWD=password123\nFILENAME=c:/temp/ololo.csv\nTESTMODE=on")
      f1.close()
   except:
      print u"Невозможно записать файл ololo.conf - ошибка"
      sys.exit(3)

setup_console()

if not isfile('phantomjs.exe'):
   print u"Ошибка:\n"+\
         "\tФайл PhantomJS.exe является необходимым драйвером браузера для работы программы"+"\n"+\
         "\tНайти последнюю его версию можно здесь: http://phantomjs.org/download.html"
   sys.exit(1)

if not isfile('renaultsend.conf'):
   print u"Ошибка:\n"+\
         "\tФайл ololo.conf является необходимым файлом конфигурации"+"\n"+\
         "\tПримерный файл конфигурации создан, ознакомьтесь если требуется"
   recreateconf()
   sys.exit(2)

url=''
login=''
passwd=''
filename=''
testmode='off'

try:
   cparser=ConfigParser.ConfigParser()
   cparser.read('renaultsend.conf')
   url=cparser.get('MAIN','URL')
   login=cparser.get('MAIN','LOGIN')
   passwd=cparser.get('MAIN','PASSWD')
   filename=cparser.get('MAIN','FILENAME')
   if cparser.has_option('MAIN','TESTMODE'):
      testmode=cparser.get('MAIN','TESTMODE')
except:
   print u"Ошибка:\n"+\
         "\tНевозможно прочитать файл либо неверный формат файла конфигурации ololo.conf\n"\
         "\tУдалите ololo.conf и перезапустите программу. Файл будет пересоздан"
   sys.exit(4)

try:
   driver=webdriver.PhantomJS()
   retcode=0
   driver.implicitly_wait(60)
   driver.get(url)
#вводим логи/пароль+ввод в поле пароля
   print u"Попытка отправки файла "+filename+"\n"
   driver.find_element_by_xpath('//*[@id="minWidth"]/div[2]/div/div[1]/div/form/input[1]').send_keys(login)
   driver.find_element_by_xpath('//*[@id="minWidth"]/div[2]/div/div[1]/div/form/input[2]').send_keys(passwd+Keys.ENTER)
   driver.find_element_by_xpath('//*[@id="minWidth"]/div[2]/div[2]/div[1]/div[3]/a').click()
   driver.find_element_by_xpath('//*[@id="minWidth"]/div[2]/div[2]/div[1]/a[2]').click()
   driver.find_element_by_xpath("//input[@type='file']").send_keys(filename)
   if testmode=="on": 
      try:
        driver.save_screenshot("result.jpg")
        print u"Включен testmode\n"+\
           "Скриншот с результатом последней страницы result.jpg сброшен успешно"
      except:
        print u"Внимание: не удалось сохранить скриншот result.jpg"
   else: 
      driver.find_element_by_xpath('//*[@id="minWidth"]/div[2]/div[2]/div[1]/form/input[2]').click()
except:
   print u"Непонятная ошибка с сайтом - возможно изменился контент или неверный логин/пароль.\n"+\
          "Если вы уверены что логин/пароль норм, попробуйте обратиться к разработчику alex~~~@zztop.ru ;)"
   retcode=5
finally:
   recreateconf()
   try:
       driver.quit()
   except:
       print u"Невозможно уничтожить созданный web driver, при работе произошла ошибка\n"

if retcode==0:
   print u"Все прошло успешно!"
sys.exit(retcode)

вторник, 27 января 2015 г.

Архивируем и отправляем в компанию "Что делать консалт" каталог STS.
Система исполнения - виндоза!

# -*- coding: utf-8 -*-
from smartgate import sendmail
from sys import exit
import os,zipfile, zlib

PATH2CONS="d:\\Consult"
PATH2ZIP=os.environ.get('tmp')+'\\sts.zip'

if not os.path.exists(PATH2CONS):
   print "Consultant not found at path:"+PATH2CONS
   exit(1)

zf=zipfile.ZipFile(PATH2ZIP,"w",zipfile.ZIP_DEFLATED)
for root,dirs,files in os.walk(PATH2CONS+'\\ADM\\STS'):
   for file in files:
      zf.write(os.path.join(root,file))

zf.close()
if 0==sendmail('192.168.0.1','mymail(собака)mycompany.ru',['blah-blah(собака)konsultant.ru'],"STS VERONIKA","have a fun :)",[PATH2ZIP]):
   os.remove(PATH2ZIP)

понедельник, 12 января 2015 г.

Задача: создаем список случайного размера из случайных элементов состоящих минимум из пяти символов, при чем каждый элемент содержит произвольные буквы (и заглавные и строчные) и цифры. Вывести массив на экран. Исполнение python3

import random
import string

def id_generator(size=6, chars=string.ascii_letters + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))

randarray1=[id_generator(random.randint(5,11)) for i in range(random.randint(70,97))]
print ("%s" % list(randarray1[i] for i in range(1,len(randarray1))))



зачем это:
если встретилось уже третий раз, то надо записать - copy/paste проще и быстрее. я ленивый..

вторник, 23 декабря 2014 г.

Задача

Естественно что изучать какой-либо язык интересно не в голой теории, а применяя кое-что из уже изученного. В юности сам себе придумаешь всякую хер.. задачи которые никогда потом не пригодятся. Само собой происходит поиск интересных задач и отсев ненужного шлака. Самые лучшие задачи для изучения - задачи которые нужны и могут быть использованы прямо вот тут и сейчас.

Именно таким образом я и пришел к задаче:
Написать прогу, которая бы заходила на сайт superjob.ru, логинилась, переходила в резюме и на нужном из них обновляла дату публикации. Естественно из консоли. Естественно чтоб можно было её повесить в cron :)

Язык исполнения: python
Инструменты: linux debian + ipython/ipython3, Chrome browser в виндозе для просмотра кодов элементов в режиме отладки, google..куда же без него.

Сходу задача показалась простой, при этом ни каких дополнительных вещей типа try-except или проверки на return из функций я решил не делать - это к сути задачи не относится и при желании может быть добавлено в любое время. Да и с другой стороны - лично я предпочитаю на стадии написания увидеть все возможные трейсбэки своими глазами, а не давить их эксепшенами. Полезно это, имхо.
Для языка python есть множество модулей с уже готовыми api для работы с web-страницами.
Присмотревшись к переписанному из perl'a в python модулю Mechanize родилась вот такая штука:

#!/usr/bin/python

from mechanize import Browser
import socks
import socket


TOR_IP = '127.0.0.1'
TOR_PORT = 9050
URL='http://spb.superjob.ru'
NAME='qwertyu@email.my'
PASSWD='password'

""" на случай если очень захочется пройти инкогнито через tor """
def enable_tor():
        socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, TOR_IP, TOR_PORT)
        socket.socket = socks.socksocket

#enable_tor()
br = Browser()
br.set_handle_robots(False)
br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]
br.set_handle_equiv(False)
html=br.open(URL)
br.select_form(name='login_form')
br['LoginForm[login]']=NAME
br['LoginForm[password]']=PASSWD
result_page = br.submit()
result_page=br.follow_link(text_regex='Моё резюме')
data = html.read()

И вот тут меня ждало разочарование. Оказывается хитрецы из superjob сделали ссылку обновления даты резюме на javascript. А mechanize ну никак не умеет работать с явой - только классический html. Дальнейшее гугленье мне рассказало про замечательный проект selenium, который умеет и яву и все что угодно потому как использует сторонние веб-движки через webdriver. В частности можно сделать так:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.get("http://www.python.org")
assert "Python" in driver.title
elem = driver.find_element_by_name("q")
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
driver.quit()


Но и здесь кроется засада. Дело в том что для того чтобы юзать webdriver firefox в таком    вот виде, надо чтобы файрфокс был установлен в системе. У меня же вообще нет иксов! Просто debian + консоль. И вообще - это виртуалка на VSphere и ставить иксы туда мне лень и вообще не надо потому как виртуалка для обкатки скриптов. С другой стороны есть возможность скачать любой из поддерживаемых selnium'ом веб-драйверов и попробовать его использовать как RemoteDriver приблизительно вот так 


from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
server_url = "http://%s:%s" % (localhost, 9015)
dc = DesiredCapabilities.HTMLUNIT
wd = webdriver.Remote(server_url, dc)
wd.get('http://www.google.com')


как услужливо подсказывает нам ipython про wbdriver:
from selenium import webdriver

In [141]: webdriver.
webdriver.Opera     webdriver.Android              webdriver.PhantomJS   
webdriver.Chrome  webdriver.Proxy           webriver.Remote  
webdriver.Safari     webdriver.Firefox  


Скачать драйвер Chrome и прицепить его через webdriver.Remote с наскоку не удалось потому как я работаю через ssh, а webdriver.Remote требует в любом случае иксового DISPLAY :0. 

Я по-быстрому забил на эту идею и присмотрелся к PhantomJS. Почему именно он? 

А потому что существует проект WebKit, на котором построены такие браузеры как Safari, Chromium/Crome и иже с ними - много их там. Но отличие PhantomJS в том, что он изначально разрабатывался как консольный вариант, без использования каких-либо GUI.

Ставим:



 apt-get update && apt-get install build-essential chrpath libssl-dev libxft-dev libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev

 cd /tmp && mkdir webkit && cd webkit

 wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.8-linux-i686.tar.bz2

 tar -jxf ./phantomjs-1.9.8-linux-i686.tar.bz2
 cp phantomjs-1.9.8-linux-i686/bin/phantomjs /usr/bin
(обязательно он должен быть на маршруте, иначе работать не будет)

проверяем:

from selenium import webdriver
driver=webdriver.PhantomJS()
driver.get('http://ya.ru')
print driver.title
driver.quit()

Яндекс

Работает! Продолжаем))

Переход по элементам страницы можно организовать как угодно. Я так думаю что придется подтянуть теорию xpath, потому как мне это очень понравилось, хоть я в нем ни бум ни тресь. Именно он (ентон самый xpath) и заменяет де-факто регулярки - так что придется, да и плюс в нете груда иныф про него.
Доступ к элементам я организовал самым простым способом: в лоб))
Еще за замечу, что есть элементы которые в классе находятся в еденичном варианте, а следовательно к таким элементам можно достучаться даже используя find_element_by_class_name
Кстати, а почему бы мне его не применить))

В общем вот что получилось в итоге:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

driver=webdriver.PhantomJS()

driver.get('http://spb.superjob.ru')
#print driver.title - проверим был ли переход можно тут, а можно и try/except

loginform=driver.find_element_by_class_name('LoginForm_link')

loginform.click()
driver.find_element_by_id('LoginForm_login').send_keys('username@mail(dot)domain')
driver.find_element_by_id('LoginForm_password').send_keys('password')
driver.find_element_by_id('LoginForm_password').send_keys(Keys.ENTER)
driver.find_element_by_link_text(u'Моё резюме').click()
driver.find_element_by_link_text(u'обновить дату публикации').click()
driver.quit()



*меня тут прибило искать форму с сабмитом и я использовал тот факт, что клавиша ВВОД обычно и есть "submit", но можно было и через вот это попробовать - это более канонично.
find_element_by_name("submit").click()


Все очень даже просто и понятно.
Задача для развития:
сделать тоже самое используя файл с coockies, Плюс куков в том, что парольи не хранятся в открытом виде, ну и вообще.

http://selenium-python.readthedocs.org/
http://www.ibm.com/developerworks/ru/library/l-python-mechanize-beautiful-soup/
http://wwwsearch.sourceforge.net/mechanize/
http://habrahabr.ru/post/65383/

have a fun
================ UPDATED 13.01.15 ======================
Ребром встал вопрос о сокрытии паролей внутри программы. Даже компиляция в .pyc-файл не очень тут спасает, потому как при просмотре файла внутри .pyc отлично видны такие вещи как username@mail(dot)domain, ну а прикинуть что из текста будет паролем - вообще несложно.
Можно конечно использовать модуль base64, он тоже кодирует, но на глаз сразу видны кодированные строки и раскодировать их вообще "нипраблема". Покопавшись и почитав я принял решение подключить модуль crypto и выбрав какой-либо метод шифрования, хитрый ключ  и размер блока, шифрануть все что надо. Вот что в итоге получилось

#!/usr/bin/python
# -*- coding: utf-8 -*-

from Crypto.Cipher import AES
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from base64 import b64decode,b64encode
from sys import exit

""" URL, LOGIN, PASSWD -сгенеренные от ключа numkey http://spb.superjob.ru, login+password"""

numkey=1234567890123456
URL='XmwrgNWXKqkkoRJDgC020R7Uq9RfuJsgey6mcfGYCug='
LOGIN='n5sr2mgr7Kj7cSnp/p1Z8qKbMqsR0VG0Z62fpJB3VrU='
PASSWD='+hS577+JJ1+w91wO7KH4n1Q=='
BLOCK_SIZE = 16
PADDING = '{'
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
EncodeAES = lambda c, s: b64encode(c.encrypt(pad(s)))
DecodeAES = lambda c, e: c.decrypt(b64decode(e)).rstrip(PADDING)
cipher = AES.new(str(numkey))
driver=webdriver.PhantomJS()

# ожидание загрузки страницы зависит от скорости инета/компа..
# да и еще PhantomJS - достаточно тормознутая хрень, делаем неявное ожидание 20 секунд
driver.implicitly_wait(20)

"""
можно по-другому, например до появления како-то элемента
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


driver = webdriver.Firefox()
driver.get('...')

// wait for svg to appear
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.TAG_NAME, 'svg')))
"""

#заключам весь процесс в секцию try/except - неизвестно на каком этапе срубится, может 
#пароль сменим внезапно.. ;)
retcode=0
try:
   driver.get(DecodeAES(cipher,URL))
   loginform=driver.find_element_by_class_name('LoginForm_link')
   loginform.click()
   driver.find_element_by_id('LoginForm_login').send_keys(DecodeAES(cipher,LOGIN))
   driver.find_element_by_id('LoginForm_password').send_keys(DecodeAES(cipher,PASSWD))
   driver.find_element_by_id('LoginForm_password').send_keys(Keys.ENTER)
   driver.find_element_by_link_text(u'Моё резюме').click()
   driver.find_element_by_link_text(u'обновить дату публикации').click()
except:
   retcode=1

driver.quit()
exit(retcode)

скомпилировав это чудо через
import py_compile
py_compile.compile('myfile.py')

я получил вполне достойный псевдобинарник, где нет видных глазу данных. Конечно, я же этот бинарник могу сломать, но не зная как выглядит ключ это нетривиально, что и требовалось.
Ни о какой сверхЪзащите здесь речи и не шло. С другой стороны, для усложнения поиска ключа, итоговый ключ можно было разнести на несколько переменных смешанных со статическими данными. Типа такого:
cr1='.-.+.\./'
cr2=random.randint(1000000000000000,9999999999999999)
cr3='$}887zO`'

размерность ключа должна быть кратной 8ми, а итоговый ключ может выглядеть так

key=cr3+str(random.randint(10000000,99999999))+cr1+cr2
что в .pyc будет выглядеть несовсем понятно.

литература:
https://www.dlitz.net/software/pycrypto/
http://selenium2.ru/docs/webdriver-advanced-usage.html

================ UPDATED 23.04.15 ======================
def superjobupdate(driver, cipher, SJURL, SJLOGIN, SJPASSWD):
   retcode=0
   try:
      driver.get(DecodeAES(cipher,SJURL))
      driver.find_element_by_class_name('LoginForm_link').click()
      driver.find_element_by_id('LoginForm_login').send_keys(DecodeAES(cipher,SJLOGIN))
      driver.find_element_by_id('LoginForm_password').send_keys(DecodeAES(cipher,SJPASSWD)+Keys.ENTER)
      driver.find_element_by_xpath('//*[@id="ng-app"]/div[2]/div/div[2]/div/div[1]/div[3]/div[2]/div[1]/a').click()
      driver.find_element_by_link_text(u'обновить дату публикации').click()
   except:
      retcode=2
   return retcode

def hhupdate(driver, cipher, HHURL, HHLOGIN, HHPASSWD):
   retcode=0
   try:
      driver.set_window_size(1400,1000)
      driver.get(DecodeAES(cipher,HHURL))
      driver.find_element_by_xpath('/html/body/div[3]/div/div[3]/div/div[2]/form/label[1]/input').send_keys(DecodeAES
      driver.find_element_by_xpath('/html/body/div[3]/div/div[3]/div/div[2]/form/label[2]/input').send_keys(DecodeAES
      driver.get(DecodeAES(cipher,HHURL)+'/applicant/resumes')
      arr=driver.find_elements_by_class_name("resumelist__resume")
      maxresumes=len(arr)
      for resumeindex in range(0,maxresumes):
              el=arr[resumeindex].find_element_by_class_name('b-resumelist-vacancyname')
              el.click()
              try:
                 driver.find_element_by_css_selector('body > div.HH-MainContent > div.g-row.m-row_content > div.g-col
              except:
                 pass
              driver.back()
              arr=driver.find_elements_by_class_name("resumelist__resume")
   except:
      retcode=20
   return retcode



четверг, 16 октября 2014 г.

перекладываем еженедельные архивы на другой диск/каталог с созданием маршрутов
скрипт работает из cygwin for windows

#!/bin/sh -x
arr=(недельный месячный)

 for dtype in ${arr[@]}; do
   for i in `ls /cygdrive/g/1c_server_backup/$dtype/torg_b* | gawk -F_ '{print $6"_"$7"_"$8}'`; do
      mkdir "/cygdrive/f/arch/1C папка 2/$dtype/$i";
      mv /cygdrive/g/1c_server_backup/$dtype/*$i* "/cygdrive/f/arch/1C папка 2/$dtype/$i";
      chmod 777 "/cygdrive/f/arch/1C папка 2/$dtype/$i/*"
   done
 done
#read -p "Press [Enter] key to start backup..."