How to use continue_route method in Playwright Python

Best Python code snippet using playwright-python

pbx.py

Source:pbx.py Github

copy

Full Screen

1"""2 This Source Code Form is subject to the terms of the Mozilla Public3 License, v. 2.0. If a copy of the MPL was not distributed with this4 file, You can obtain one at http://mozilla.org/MPL/2.0/.5 Software distributed under the License is distributed on an "AS IS"6 basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the7 License for the specific language governing rights and limitations8 under the License.9 The Original Code is FreePyBX/VoiceWARE.10 The Initial Developer of the Original Code is Noel Morgan,11 Copyright (c) 2011-2012 VoiceWARE Communications, Inc. All Rights Reserved.12 http://www.vwci.com/13 You may not remove or alter the substance of any license notices (including14 copyright notices, patent notices, disclaimers of warranty, or limitations15 of liability) contained within the Source Code Form of the Covered Software,16 except that You may alter any license notices to the extent required to17 remedy known factual inaccuracies.18"""19import logging20import datetime21from datetime import datetime22from pylons import request, response, session, tmpl_context as c, url23from pylons import config24from pylons.controllers.util import abort, redirect25from freepybx.lib.base import BaseController, render26from freepybx.model import meta27from freepybx.model.meta import *28from freepybx.model.meta import Session as db29from genshi import HTML30from pylons.decorators.rest import restrict31import formencode32from formencode import validators33from freepybx.lib.pymap.imap import Pymap34from freepybx.lib.auth import *35from freepybx.lib.forms import *36from freepybx.lib.util import *37from freepybx.lib.validators import *38from decorator import decorator39from pylons.decorators import jsonify40import formencode41from formencode import validators42from pylons.decorators import validate43from simplejson import loads, dumps44import simplejson as json45import os, sys46from subprocess import call47from stat import *48import simplejson as json49from simplejson import loads, dumps50import urllib51from sqlalchemy import Date, cast, desc, asc52from sqlalchemy.orm import join53import time54import shutil55import cgi56import cgitb; cgitb.enable()57from ESL import *58import re59import csv60logged_in = IsLoggedIn()61credential = HasCredential62log = logging.getLogger(__name__)63DEBUG=False64fs_vm_dir = config['app_conf']['fs_vm_dir']65fs_dir = config['app_conf']['fs_dir']66ESL_HOST = config['app_conf']['esl_host']67ESL_PORT = config['app_conf']['esl_port']68ESL_PASS = config['app_conf']['esl_pass']69class PbxController(BaseController):70 """ This is the main controller for the config of the pbx. FreeSWITCH71 makes requests from the curl xml interface when the configuration72 is requested from FreeSWITCH."""73 def index(self):74 return "<Nothing/>"75 def sofiaconf(self):76 c.domains = []77 c.odbc_credentials = config['app_conf']['odbc_credentials']78 c.pbx_profiles = PbxProfile.query.all()79 c.pbx_gateways = PbxGateway.query.all()80 c.pbx_acl_blacklist = PbxAclBlacklist.query.all()81 for domain in PbxContext.query.filter_by(profile=c.pbx_profiles[0].name).all():82 c.domains.append(domain.domain)83 return render('xml/sofia.conf.xml')84 def switchconf(self):85 c.odbc_credentials = config['app_conf']['odbc_credentials']86 return render('xml/switch.conf.xml')87 def aclconf(self):88 c.pbx_gateways = PbxGateway.query.all()89 c.pbx_acl_blacklist = PbxAclBlacklist.query.all()90 c.odbc_credentials = config['app_conf']['odbc_credentials']91 return render('xml/switch.conf.xml')92 def callcenterconf(self):93 c.odbc_credentials = config['app_conf']['odbc_credentials']94 c.domains = []95 c.call_center_queues = []96 c.call_center_agents = []97 c.call_center_tiers = []98 try:99 for domain in PbxContext.query.distinct(PbxContext.domain).all():100 c.domains.append(domain.domain)101 for context in PbxContext.query.distinct(PbxContext.context):102 for queue in CallCenterQueue.query.filter_by(context=context.context).all():103 c.call_center_queues.append(104 {'name': queue.name, 'domain': queue.domain, 'moh_sound': queue.moh_sound.split(",")[1],105 'time_base_score': queue.time_base_score,106 'max_wait_time': queue.max_wait_time,107 'max_wait_time_with_no_agent': queue.max_wait_time_with_no_agent,108 'max_wait_time_with_no_agent_reached': queue.max_wait_time_with_no_agent_reached,109 'tier_rules_apply': queue.tier_rules_apply,110 'tier_rule_wait_second': queue.tier_rule_wait_second,111 'tier_rule_wait_multiply_level': queue.tier_rule_wait_multiply_level,112 'record_calls': queue.record_calls,113 'tier_rule_agent_no_wait': queue.tier_rule_agent_no_wait,114 'discard_abandoned_after': queue.discard_abandoned_after,115 'abandoned_resume_allowed': queue.abandoned_resume_allowed, 'strategy': queue.strategy,116 'announce_sound': queue.announce_sound,117 'announce_frequency': queue.announce_frequency})118 for agent in CallCenterAgent.query.filter_by(context=context.context).all():119 c.call_center_agents.append({'name': agent.name, 'domain': queue.domain, 'type': agent.type,120 'max_no_answer': agent.max_no_answer, 'extension': agent.extension,121 'wrap_up_time': agent.wrap_up_time,122 'reject_delay_time': agent.reject_delay_time,123 'busy_delay_time': agent.busy_delay_time,124 'timeout': agent.timeout})125 for tier in CallCenterTier.query.all():126 c.call_center_tiers.append({'agent': tier.agent, 'domain': queue.domain, 'queue': tier.queue,127 'level': tier.level, 'position': tier.position})128 except:129 return render('xml/notfound.xml')130 return render('xml/callcenter.conf.xml')131 def cdr_pg_csvconf(self):132 return render('xml/cdr_pg_csv.conf.xml')133 def dbconf(self):134 c.odbc_credentials = config['app_conf']['odbc_credentials']135 return render('xml/db.conf.xml')136 def faxconf(self):137 return render('xml/fax.conf.xml')138 def fifoconf(self):139 c.domains=[]140 for domain in PbxContext.query.distinct(PbxContext.domain).all():141 c.domains.append(domain.domain)142 c.odbc_credentials = config['app_conf']['odbc_credentials']143 return render('xml/fifo.conf.xml')144 def presence_mapconf(self):145 c.domains = []146 for domain in PbxContext.query.filter_by(profile=c.pbx_profiles[0].name).all():147 c.domains.append(domain.domain)148 return render('xml/presence_map.conf.xml')149 def voicemailconf(self):150 c.odbc_credentials = config['app_conf']['odbc_credentials']151 c.pbx_profiles = PbxProfile.query.all()152 return render('xml/voicemail.conf.xml')153 def lcrconf(self):154 c.odbc_credentials = config['app_conf']['odbc_credentials']155 c.pbx_profiles = PbxProfile.query.all()156 return render('xml/lcr.conf.xml')157 def configuration(self, **kw):158 conf = re.sub('[^A-Za-z0-9]+', '', request.params.get('key_value', "Nothing"))159 if has_method(self, conf):160 return getattr(self, conf)()161 else:162 return render('xml/notfound.xml')163 def directory(self, **kw):164 """ The directory method is called when FreeSWITCH needs information165 about the users endpoints and for things like gateways for the 166 profile, group pointers, as well as our custom stuff like virtual167 mailbox extensions. All specific to XML. Needed for registrations 168 and XML. """169 try:170 if request.params.has_key('purpose'):171 if request.params["purpose"] == "gateways":172 gateway = db.execute("SELECT pbx_gateways.* FROM pbx_gateways "173 "INNER JOIN pbx_profiles "174 "ON pbx_profiles.id = pbx_gateways.pbx_profile_id "175 "WHERE pbx_profiles.name = :profile_name",176 {'profile_name': str(request.params["profile"])})177 c.gateway = {'name': str(request.params["profile"]), 'gateway': gateway}178 db.remove()179 return render('xml/gateways.xml')180 domain = request.params.get('domain', None)181 if not db.query(Customer.active).join(PbxContext).filter(PbxContext.domain==domain).filter(Customer.active==True).first():182 return render('xml/notfound.xml')183 c.groups = []184 c.voicemailboxes = []185 for group in PbxGroup.query.filter_by(context=domain).all():186 exts = []187 for ext in PbxGroupMember.query.filter_by(pbx_group_id=group.id).all():188 exts.append({'ext': ext.extension})189 c.groups.append({'name': group.name, 'extensions': exts})190 for vmext in PbxVirtualMailbox.query.filter_by(context=domain).all():191 c.voicemailboxes.append({'extension': vmext.extension, 'vm_password': vmext.vm_password,192 'vm_attach_email': vmext.vm_attach_email, 'vm_save': vmext.vm_save,193 'vm_notify_email': vmext.vm_notify_email, 'vm_email': vmext.vm_email})194 if not request.params.has_key('user'):195 c.endpoints = []196 c.domain = domain197 c.endpoints = PbxEndpoint.query.filter_by(user_context = domain).all()198 return render('xml/directory.xml')199 else:200 user = request.params.get('user')201 c.domain = domain202 c.endpoints = PbxEndpoint.query.filter_by(user_context = domain).filter_by(auth_id=user).all()203 if not len(c.endpoints):204 for vmext in PbxVirtualMailbox.query.filter_by(context=domain).all():205 c.voicemailboxes.append({'extension': vmext.extension, 'vm_password': vmext.vm_password,206 'vm_attach_email': vmext.vm_attach_email, 'vm_save': vmext.vm_save,207 'vm_notify_email': vmext.vm_notify_email, 'vm_email': vmext.vm_email})208 if c.voicemailboxes:209 return render('xml/virtual_mailboxes.xml')210 else:211 return render('xml/notfound.xml')212 return render('xml/directory.xml')213 except:214 return render('xml/notfound.xml')215 finally:216 db.remove()217 def dialplan(self, **kw):218 """ This is a recursion engine that creates several objects of nested219 dictionaries and arrays and that are subsequently passed into the220 template context of pylons and interpolated into the xml template221 stream by genshi to create XML dynamically for FreeSWITCH.222 We create this for call control as well as use lua for setting223 inbound routes by context from the default context, since we are224 using only one profile for all sip traffic. Both the XML and lua225 call control are needed. It helps you be lazy and hardcode trash226 into the dialplan that you will eventually forget about.227 :param c.profile: request parameter posted from FreeSWITCH228 :type c.profile: type description229 :returns context object230 :rtype: serialized Dict231 :returns dids object232 :rtype: serialized Dict233 Renders: ``xml/dialplan.xml``234 I'll highlight the important stuff.235 Pull all of the dids from the db to setup call control for lua236 from the default context on incoming calls from outside the switch.237 Iterate over the contexts and create objects for the xml stream engine.238 These objects are passed to dialplan.xml in the templates/xml directory.239 Retrieve all of the routes.240 Only concerned with what is needed for transfers to the xml context.241 More to do in xml with virtual extensions for things like continue on fail242 timeouts to local voicemail boxes.243 After we check and make sure that our route object is iterable,244 we grab the conditions and actions for the route. We have a template245 meta class and default set of conditions/actions for orphaned routes.246 Not really needed, but it will help you when you make mistakes your247 users will still get dialplan.248 Retrieve the route conditions and actions for the conditions.249 Serialize into context template and pass objects to xml rendering stream.250 """251 c.contexts = []252 routes = []253 conditions = []254 actions = []255 c.profile = request.params.get('variable_sofia_profile_name','default')256 try:257 c.dids = PbxDid.query.join(Customer).filter(Customer.active==True).filter(PbxDid.active==True).all()258 for context in PbxContext.query.join(Customer).filter(Customer.active==True).distinct(PbxContext.context):259 conference_bridges = PbxConferenceBridge.query.filter_by(context=context.context).all()260 voicemailboxes = PbxVirtualMailbox.query.filter_by(context=context.context).all()261 faxes = PbxFax.query.filter_by(context=context.context).all()262 gateway = PbxGateway.query.join(PbxProfile).filter(PbxProfile.name==c.profile).first()263 for route in PbxRoute.query.filter_by(context=context.context).all():264 ep = None265 if route.pbx_route_type_id not in range(1,3):266 continue267 if route.pbx_route_type_id == 2:268 continue269 route_conditions = is_iter_obj(PbxCondition.query.filter_by(pbx_route_id=route.id).all())270 if route.pbx_route_type_id == 1:271 ep = PbxEndpoint.query.filter_by(id=route.pbx_to_id).first()272 user = User.query.filter_by(id=ep.user_id).first()273 rec = ep.record_inbound_calls274 else:275 rec = None276 if route_conditions is not None:277 for condition in route_conditions:278 for action in PbxAction.query.filter_by(pbx_condition_id=condition.id).order_by(PbxAction.precedence).all():279 actions.append({'application': action.application, 'data': action.data})280 ds = get_findme(route.name, context.context)281 if len(ds):282 actions.append({'application': "set", 'data': "ignore_early_media=true"})283 for d in ds:284 actions.append({'application': "set", 'data': "call_timeout="+str(ep.call_timeout)})285 actions.append({'application': "bridge", 'data': d})286 conditions.append({'field': condition.field, 'expression': condition.expression, 'actions': actions})287 actions = []288 else:289 for action in PbxActionTmpl.query.join(PbxConditionTmpl).filter(PbxConditionTmpl.pbx_route_type_id==route.pbx_route_type_id).order_by(PbxActionTmpl.precedence).all():290 actions.append({'application': action.application, 'data': action.data})291 actions.append({'application': "bridge", 'data': "sofia/"+str(get_profile())+"/$1"+"%"+context.context})292 conditions.append({'field': "destination_number", 'expression': "^("+route.name+")", 'actions': actions})293 actions = []294 routes.append({'name': route.name, 'continue_route': str(route.continue_route).lower(), 'conditions': conditions, 'user_id': user.id, 'customer_id': user.customer_id,295 'voicemail_enabled': str(route.voicemail_enabled).lower(), 'voicemail_ext': route.voicemail_ext, 'record_inbound_calls': rec})296 conditions = []297 c.contexts.append({'domain': context.domain, 'context': context.context, 'routes': routes, 'effective_caller_id_name': context.caller_id_name,298 'effective_caller_id_number': context.caller_id_number, 'origination_caller_id_name': context.caller_id_name,299 'origination_caller_id_number': context.caller_id_number, 'gateway': gateway.name, 'conference_bridges': conference_bridges,300 'voicemailboxes': voicemailboxes, 'faxes': faxes, 'recordings_dir': fs_vm_dir+context.domain+"/recordings/"})301 routes = []302 db.remove()303 return render('xml/dialplan.xml')304 except Exception, e:305 return render('xml/notfound.xml')306 finally:307 db.remove()308 def doc_pbx_json(self):309 """ Below is the JSON data called for the pbx by dojo and/or the template310 context. The json decorators do not work because postgres scary date311 objects are not serializable, so they have to be string formatted or312 worse, passed to the json encoder class and serialized by type313 reference. The encoder is imported from the lib.util.314 Lots of work needs to be done like meta class init functions for315 inserts, but as I rollout subsequent versions, stored procedures316 will eventually replace much of the way sqlalchemy handles the data317 and I prefer not to do it more than once ;p"""318 @authorize(logged_in)319 def users(self):320 items=[]321 exts = []322 for row in User.query.filter(User.customer_id==session['customer_id']).order_by(asc(User.id)).all():323 for ext in PbxEndpoint.query.filter(PbxEndpoint.user_id==row.id).filter_by(user_context=session['context']).all():324 exts.append(ext.auth_id)325 if not len(exts) > 0:326 extension = "No Extension"327 else:328 extension = ",".join(exts)329 items.append({'id': row.id, 'extension': extension, 'username': row.username, 'password': row.password, 'first_name': row.first_name, 'name': row.first_name +' '+row.last_name,330 'last_name': row.last_name, 'address': row.address, 'address_2': row.address_2, 'city': row.city, 'state': row.state, 'zip': row.zip,331 'tel': row.tel, 'mobile': row.mobile, 'notes': row.notes, 'created': row.created.strftime("%m/%d/%Y %I:%M:%S %p"), 'updated': row.updated.strftime("%m/%d/%Y %I:%M:%S %p"), 'active': row.active,332 'group_id': row.group_id, 'last_login': row.last_login.strftime("%m/%d/%Y %I:%M:%S %p"), 'remote_addr': row.remote_addr, 'session_id': row.session_id, 'customer_id': row.customer_id})333 exts = []334 db.remove()335 out = dict({'identifier': 'id', 'label': 'name', 'items': items})336 response = make_response(out)337 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]338 return response(request.environ, self.start_response)339 @authorize(logged_in)340 def user_by_id(self, id, **kw):341 items=[]342 exts = []343 for row in User.query.filter(User.customer_id==session['customer_id']).filter(User.id==id).order_by(asc(User.id)).all():344 for ext in PbxEndpoint.query.filter(PbxEndpoint.user_id==row.id).all():345 exts.append(ext.auth_id)346 if not len(exts) > 0:347 extension = "No Extension"348 else:349 extension = ",".join(exts)350 items.append({'id': row.id, 'extension': extension, 'username': row.username, 'password': row.password, 'first_name': row.first_name, 'portal_extension': row.portal_extension,351 'last_name': row.last_name, 'address': row.address, 'address_2': row.address_2, 'city': row.city, 'state': row.state, 'zip': row.zip,352 'tel': row.tel, 'mobile': row.mobile, 'notes': row.notes, 'created': row.created.strftime("%m/%d/%Y %I:%M:%S %p"), 'updated': row.updated.strftime("%m/%d/%Y %I:%M:%S %p"), 'active': row.active,353 'group_id': row.group_id, 'last_login': row.last_login.strftime("%m/%d/%Y %I:%M:%S %p"), 'remote_addr': row.remote_addr, 'session_id': row.session_id, 'customer_id': row.customer_id})354 exts = []355 db.remove()356 out = dict({'identifier': 'id', 'label': 'name', 'items': items})357 response = make_response(out)358 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]359 return response(request.environ, self.start_response)360 @restrict("POST")361 @authorize(logged_in)362 def add_user(self, **kw):363 schema = UserForm()364 try:365 form_result = schema.to_python(request.params)366 u = User()367 u.username = form_result.get("username")368 u.password = form_result.get("password")369 u.first_name = form_result.get("first_name")370 u.last_name = form_result.get("last_name")371 u.address = form_result.get("address")372 u.address_2 = form_result.get("address_2")373 u.city = form_result.get("city")374 u.state = form_result.get("state")375 u.zip = form_result.get("zip")376 u.tel = form_result.get("tel")377 u.mobile = form_result.get("mobile")378 u.active = form_result.get("active")379 u.customer_id = session["customer_id"]380 u.notes = form_result.get("notes")381 u.portal_extension = form_result.get("extension")382 g = Group.query.filter(Group.id==form_result.get("group_id",2)).first()383 g.users.append(u)384 db.add(g)385 db.commit(); db.flush()386 context = PbxContext.query.filter(PbxContext.customer_id==session['customer_id']).first()387 em = EmailAccount()388 e = PbxEndpoint()389 r = PbxRoute()390 c = PbxCondition()391 s = PbxAction()392 if(session['has_crm']):393 if len(form_result.get("email"))>0 and len(form_result.get("email_password"))>0 and len(form_result.get("email_server"))>0:394 em = EmailAccount()395 em.user_id = u.id396 em.customer_id = session['customer_id']397 em.email = form_result.get("email")398 em.password = form_result.get("email_password")399 em.mail_server = form_result.get("email_server")400 email = form_result.get("email", None)401 db.add(em)402 db.commit()403 db.flush()404 else:405 email = ""406 if request.params.has_key('extension'):407 ext = form_result.get("extension").strip()408 if ext.isdigit():409 if (len(get_extensions(ext))>0):410 raise Exception("Extension already exists!")411 ext_failed = True412 else:413 ext_failed = False414 else:415 ext_failed = True416 else:417 ext_failed = True418 if not ext_failed:419 e = PbxEndpoint()420 e.auth_id = form_result.get("extension")421 e.password = form_result.get("extension_password")422 e.outbound_caller_id_name = context.caller_id_name423 e.outbound_caller_id_number = context.caller_id_number424 e.internal_caller_id_name = u.first_name + ' ' + u.last_name425 e.internal_caller_id_number = form_result.get("extension")426 e.user_context = context.context427 e.force_transfer_context = context.context428 e.user_originated = u'true'429 e.toll_allow = u'domestic'430 e.call_timeout = form_result.get("call_timeout", 20)431 e.accountcode = context.caller_id_number432 e.pbx_force_contact = form_result.get("pbx_force_contact", u'nat-connectile-dysfunction')433 e.vm_email = form_result.get("vm_email")434 e.vm_password = form_result.get("vm_password")435 e.vm_attach_email = True if form_result.get("vm_email", None) is not None else False436 e.vm_delete = False437 e.user_id = u.id438 db.add(e)439 db.commit(); db.flush()440 r = PbxRoute()441 r.context = context.context442 r.domain = context.context443 r.name = form_result.get("extension")444 r.continue_route = True445 r.voicemail_enable = True446 r.voicemail_ext = form_result.get("extension")447 r.pbx_route_type_id = 1448 r.pbx_to_id = e.id449 db.add(r)450 db.commit(); db.flush()451 con = PbxCondition()452 con.context = context.context453 con.domain = context.context454 con.field = u'destination_number'455 con.expression = u'^('+form_result.get("extension")+')$'456 con.pbx_route_id = r.id457 db.add(c)458 db.commit(); db.flush()459 s = PbxAction()460 s.pbx_condition_id = con.id461 s.context = context.context462 s.domain = context.context463 s.precedence = 1464 s.application = u'set'465 s.data = u'hangup_after_bridge=true'466 db.add(s)467 db.commit(); db.flush()468 s = PbxAction()469 s.pbx_condition_id = con.id470 s.context = context.context471 s.domain = context.context472 s.precedence = 2473 s.application = u'set'474 s.data = u'call_timeout=20'475 db.add(s)476 db.commit(); db.flush()477 s = PbxAction()478 s.pbx_condition_id = con.id479 s.context = context.context480 s.domain = context.context481 s.precedence = 3482 s.application = u'bridge'483 s.data = u'{force_transfer_context='+context.context+'}sofia/'+str(get_profile())+'/'+form_result.get("extension")+'%'+context.context484 db.add(s)485 db.commit(); db.flush()486 except validators.Invalid, error:487 db.remove()488 return 'Validation Error: %s' % error489 db.remove()490 return "Sucessfully added user."491 @restrict("POST")492 @authorize(logged_in)493 def edit_user(self, **kw):494 schema = UserEditForm()495 try:496 form_result = schema.to_python(request.params)497 u = User.query.filter(User.id==form_result.get("id")).filter(User.customer_id==session['customer_id']).first()498 if form_result.get("username") != u.username:499 if not get_usernames(str(form_result.get("username", None))):500 u.username = form_result.get("username")501 u.password = form_result.get("password")502 u.first_name = form_result.get("first_name")503 u.last_name = form_result.get("last_name")504 u.address = form_result.get("address")505 u.address_2 = form_result.get("address_2")506 u.city = form_result.get("city")507 u.state = form_result.get("state")508 u.zip = form_result.get("zip")509 u.tel = form_result.get("tel")510 u.mobile = form_result.get("mobile")511 u.portal_extension = form_result.get('extension', 0)512 u.active = True if form_result.get("active", None) is not None else False513 u.customer_id = session["customer_id"]514 u.notes = form_result.get("notes")515 db.commit(); db.flush()516 db.execute("UPDATE user_groups SET group_id = :group_id where user_id = :user_id",\517 {'group_id': form_result.get('group_id', 3) , 'user_id': u.id})518 db.commit(); db.flush()519 db.remove()520 except validators.Invalid, error:521 return 'Error updating user. Please contact support.'522 return "User successfully updated."523 @authorize(logged_in)524 def update_users_grid(self, **kw):525 w = loads(urllib.unquote_plus(request.params.get("data")))526 for i in w['modified']:527 u = User.query.filter_by(customer_id=session['customer_id']).filter_by(id=i['id']).first()528 u.first_name = i['first_name']529 u.last_name = i['last_name']530 u.username = i['username']531 u.password = i['password']532 db.commit(); db.flush()533 db.remove()534 return "Successfully updated users."535 @restrict("GET")536 @authorize(logged_in)537 def del_user(self, **kw):538 u = User.query.filter(User.id==request.params['id']).filter(User.customer_id==session['customer_id']).first()539 delete_extension_by_user_id(u.id)540 try:541 id = request.params['id']542 if not id.isdigit():543 raise Exception("YOUR IP: "+str(request.params["HTTP_REMOTE_DUDE"])+" INFO WAS SENT TO THE ADMIN FOR BLOCKING.")544 User.query.filter(User.id==id).filter(User.customer_id==session['customer_id']).delete()545 db.commit(); db.flush()546 except:547 db.remove()548 return "Error deleting user."549 db.remove()550 return "Successfully deleted user."551 @authorize(logged_in)552 def extensions(self):553 items=[]554 ep_stats = []555 for endpoint in PbxEndpoint.query.filter(PbxEndpoint.user_context==session['context']).all():556 for pbx_reg in PbxRegistration.query.filter(PbxRegistration.sip_realm==session['context']).filter(PbxRegistration.sip_user==endpoint.auth_id).all():557 ep_stats.append({'ip': pbx_reg.network_ip, 'port': pbx_reg.network_port})558 is_online = True if len(ep_stats) > 0 else False559 if is_online:560 ip = ep_stats[0]["ip"]561 port = ep_stats[0]["port"]562 else:563 ip = "Unregistered"564 port = "N/A"565 for user in User.query.filter_by(id=endpoint.user_id).all():566 items.append({'id': endpoint.id, 'name': str(user.first_name)+' '+str(user.last_name), 'extension': endpoint.auth_id, 'password': endpoint.password,567 'outbound_caller_id_name': endpoint.outbound_caller_id_name, 'outbound_caller_id_number': endpoint.outbound_caller_id_number,568 'internal_caller_id_name': endpoint.internal_caller_id_name, 'internal_caller_id_number': endpoint.internal_caller_id_number,569 'vm_email': endpoint.vm_email, 'vm_password': endpoint.vm_password, 'vm_save': endpoint.vm_save,'vm_attach_email': endpoint.vm_attach_email,570 'vm_notify_email': endpoint.vm_notify_email, 'mac': endpoint.mac, 'device_type_id': endpoint.device_type_id,571 'transfer_fallback_extension': endpoint.transfer_fallback_extension, 'is_online': is_online, 'ip': ip, 'port': port,572 'auto_provision': endpoint.auto_provision})573 ep_stats = []574 db.remove()575 out = dict({'identifier': 'extension', 'label': 'name', 'items': items})576 response = make_response(out)577 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]578 return response(request.environ, self.start_response)579 @authorize(logged_in)580 def extension_by_id(self, id, **kw):581 items=[]582 for endpoint in PbxEndpoint.query.filter(PbxEndpoint.user_context==session['context']).filter(PbxEndpoint.id==id).all():583 for user in User.query.filter_by(id=endpoint.user_id).all():584 items.append({'id': endpoint.id, 'name': str(user.first_name)+' '+str(user.last_name), 'extension': endpoint.auth_id, 'password': endpoint.password,585 'outbound_caller_id_name': endpoint.outbound_caller_id_name, 'outbound_caller_id_number': endpoint.outbound_caller_id_number,586 'internal_caller_id_name': endpoint.internal_caller_id_name, 'internal_caller_id_number': endpoint.internal_caller_id_number,587 'vm_email': endpoint.vm_email, 'vm_password': endpoint.vm_password, 'vm_attach_email': endpoint.vm_attach_email, 'vm_save': endpoint.vm_save,588 'vm_notify_email': endpoint.vm_notify_email, 'calling_rule_id': endpoint.calling_rule_id,589 'transfer_fallback_extension': endpoint.transfer_fallback_extension, 'find_me': endpoint.find_me, 'follow_me_1': endpoint.follow_me_1,590 'follow_me_2': endpoint.follow_me_2, 'follow_me_3': endpoint.follow_me_3, 'follow_me_4': endpoint.follow_me_4, 'call_timeout': endpoint.call_timeout,591 'timeout_destination': endpoint.timeout_destination, 'record_inbound_calls': endpoint.record_inbound_calls, 'record_outbound_calls': endpoint.record_outbound_calls,592 'mac': endpoint.mac, 'device_type_id': endpoint.device_type_id, 'auto_provision': endpoint.auto_provision, 'include_xml_directory': endpoint.include_xml_directory})593 db.remove()594 out = dict({'identifier': 'extension', 'label': 'name', 'items': items})595 response = make_response(out)596 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]597 return response(request.environ, self.start_response)598 @authorize(logged_in)599 def add_extension(self):600 schema = ExtensionForm()601 msg=""602 co = Customer.query.filter(Customer.id==session['customer_id']).first()603 try:604 form_result = schema.to_python(request.params)605 e = PbxEndpoint()606 e.auth_id = form_result.get('extension')607 e.password = form_result.get('password')608 e.outbound_caller_id_name = form_result.get('outbound_caller_id_name')609 e.outbound_caller_id_number = form_result.get('outbound_caller_id_number')610 e.internal_caller_id_name = form_result.get('internal_caller_id_name')611 e.internal_caller_id_number = form_result.get('internal_caller_id_number')612 e.vm_email = form_result.get('vm_email')613 e.vm_password = form_result.get('vm_password')614 e.vm_attach_email = form_result.get('vm_attach_email')615 e.vm_notify_email = form_result.get('vm_notify_email')616 e.vm_save = form_result.get('vm_save')617 e.transfer_fallback_extension = form_result.get('transfer_fallback_extension')618 e.accountcode = co.tel619 e.follow_me_1 = form_result.get('follow_me_1')620 e.follow_me_2 = form_result.get('follow_me_2')621 e.follow_me_3 = form_result.get('follow_me_3')622 e.follow_me_4 = form_result.get('follow_me_4')623 e.call_timeout = form_result.get('call_timeout', 20)624 time_dest = form_result.get('timeout_destination')625 e.timeout_destination = time_dest if time_dest.isdigit() else None626 e.record_inbound_calls = form_result.get('record_inbound_calls', False)627 e.record_outbound_calls = form_result.get('record_outbound_calls', False)628 e.user_id = int(session['user_id'])629 e.user_context = session['context']630 e.force_transfer_context = session['context']631 e.user_originated = u'true'632 e.toll_allow = u'domestic'633 e.accountcode = co.tel634 e.calling_rule_id = form_result.get('calling_rule_id')635 e.find_me = True if form_result.get('find_me')=="true" else False636 e.auto_provision = True if form_result.get('auto_provision')=="true" else False637 e.device_type_id = form_result.get('device_type_id') if form_result.get('device_type_id') else 0638 e.include_xml_directory = True if form_result.get('include_xml_directory')=="true" else False639 e.mac = form_result.get('mac', None)640 db.add(e)641 db.commit(); db.flush()642 r = PbxRoute()643 r.context = session['context']644 r.domain = session['context']645 r.name = form_result.get("extension")646 r.continue_route = True647 r.voicemail_enable = True648 r.voicemail_ext = form_result.get("extension")649 r.pbx_route_type_id = 1650 r.pbx_to_id = e.id651 db.add(r)652 db.commit(); db.flush()653 con = PbxCondition()654 con.context = session['context']655 con.domain = session['context']656 con.field = u'destination_number'657 con.expression = u'^('+form_result.get("extension")+')$'658 con.pbx_route_id = r.id659 db.add(con)660 db.commit(); db.flush()661 s = PbxAction()662 s.pbx_condition_id = con.id663 s.context = session['context']664 s.domain = session['context']665 s.precedence = 1666 s.application = u'set'667 s.data = u'hangup_after_bridge=true'668 db.add(s)669 db.commit(); db.flush()670 s = PbxAction()671 s.pbx_condition_id = con.id672 s.context = session['context']673 s.domain = session['context']674 s.precedence = 1675 s.application = u'set'676 s.data = u'continue_on_fail=true'677 db.add(s)678 db.commit(); db.flush()679 s = PbxAction()680 s.pbx_condition_id = con.id681 s.context = session['context']682 s.domain = session['context']683 s.precedence = 2684 s.application = u'set'685 s.data = u'call_timeout='+form_result.get('call_timeout', 20)686 db.add(s)687 db.commit(); db.flush()688 s = PbxAction()689 s.pbx_condition_id = con.id690 s.context = session['context']691 s.domain = session['context']692 s.precedence = 3693 s.application = u'bridge'694 s.data = u'{force_transfer_context='+session['context']+'}sofia/'\695 +str(get_profile())+'/'+form_result.get("extension")+'%'+session['context']696 db.add(s)697 db.commit(); db.flush()698 except validators.Invalid, error:699 db.remove()700 return 'Validation Error: %s' % error701 return "Successfully added extension %s" % form_result.get('extension')702 @restrict("POST")703 @authorize(logged_in)704 def edit_extension(self, **kw):705 schema = ExtEditForm()706 msg=""707 try:708 form_result = schema.to_python(request.params)709 e = PbxEndpoint.query.filter(PbxEndpoint.id==form_result.get('extension_id')).filter(PbxEndpoint.user_context==session['context']).first()710 e.password = form_result.get('password')711 e.outbound_caller_id_name = form_result.get('outbound_caller_id_name')712 e.outbound_caller_id_number = form_result.get('outbound_caller_id_number')713 e.internal_caller_id_name = form_result.get('internal_caller_id_name')714 e.internal_caller_id_number = form_result.get('internal_caller_id_number')715 e.vm_email = form_result.get('vm_email')716 e.vm_password = form_result.get('vm_password')717 e.vm_attach_email = True if form_result.get('vm_attach_email')=="true" else False718 e.vm_notify_email = True if form_result.get('vm_notify_email')=="true" else False719 e.vm_save = True if form_result.get('vm_save')=="true" else False720 e.transfer_fallback_extension = form_result.get('transfer_fallback_extension')721 e.follow_me_1 = form_result.get('follow_me_1')722 e.follow_me_2 = form_result.get('follow_me_2')723 e.follow_me_3 = form_result.get('follow_me_3')724 e.follow_me_4 = form_result.get('follow_me_4')725 e.call_timeout = form_result.get('call_timeout')726 time_dest = form_result.get('timeout_destination')727 e.find_me = True if form_result.get('find_me')=="true" else False728 e.timeout_destination = time_dest if time_dest.isdigit() else None729 e.record_inbound_calls = form_result.get('record_inbound_calls', False)730 e.record_outbound_calls = form_result.get('record_outbound_calls', False)731 e.auto_provision = True if form_result.get('auto_provision')=="true" else False732 e.device_type_id = form_result.get('device_type_id') if form_result.get('device_type_id') else 0733 e.include_xml_directory = True if form_result.get('include_xml_directory')=="true" else False734 e.mac = form_result.get('mac', None)735 e.calling_rule_id = form_result.get('calling_rule_id')736 db.add(e)737 db.commit(); db.flush()738 r = PbxRoute.query.filter(PbxRoute.pbx_route_type_id==1).\739 filter(PbxRoute.name==e.auth_id).filter(PbxRoute.context==session['context']).first()740 delete_conditions(r.id)741 con = PbxCondition()742 con.context = session['context']743 con.domain = session['context']744 con.field = u'destination_number'745 con.expression = u'^('+e.auth_id+')$'746 con.pbx_route_id = r.id747 db.add(con)748 db.commit(); db.flush()749 s = PbxAction()750 s.pbx_condition_id = con.id751 s.context = session['context']752 s.domain = session['context']753 s.precedence = 1754 s.application = u'set'755 s.data = u'hangup_after_bridge=true'756 db.add(s)757 db.commit(); db.flush()758 s = PbxAction()759 s.pbx_condition_id = con.id760 s.context = session['context']761 s.domain = session['context']762 s.precedence = 1763 s.application = u'set'764 s.data = u'continue_on_fail=true'765 db.add(s)766 db.commit(); db.flush()767 s = PbxAction()768 s.pbx_condition_id = con.id769 s.context = session['context']770 s.domain = session['context']771 s.precedence = 2772 s.application = u'set'773 s.data = u'call_timeout='+form_result.get('call_timeout', 20)774 db.add(s)775 db.commit(); db.flush()776 s = PbxAction()777 s.pbx_condition_id = con.id778 s.context = session['context']779 s.domain = session['context']780 s.precedence = 3781 s.application = u'bridge'782 s.data = u'{force_transfer_context='+session['context']+'}sofia/'+str(get_profile())+'/'+e.auth_id+'%'+session['context']783 db.add(s)784 db.commit(); db.flush()785 db.remove()786 except validators.Invalid, error:787 msg='Validation Error: %s' % error788 finally:789 if len(msg)>0:790 return msg791 else:792 return "Successfully edited extension %s" % e.auth_id793 db.remove()794 @authorize(logged_in)795 def update_ext_grid(self, **kw):796 w = loads(urllib.unquote_plus(request.params.get("data")))797 e = None798 for i in w['modified']:799 if i['name'].isdigit():800 id = i['name']801 u = User.query.filter(User.id==int(id)).filter_by(customer_id=session['customer_id']).first()802 e = PbxEndpoint.query.filter(PbxEndpoint.auth_id==i['extension']).filter_by(user_context=session['context']).first()803 e.user_id = u.id804 else:805 e = PbxEndpoint.query.filter(PbxEndpoint.auth_id==i['extension']).filter_by(user_context=session['context']).first()806 e.password = i['password']807 db.commit(); db.flush()808 db.remove()809 return "Successfully updated extension."810 @restrict("GET")811 @authorize(logged_in)812 def del_ext(self, **kw):813 try:814 delete_extension_by_ext(request.params['extension'])815 except:816 return "Error deleting extension."817 return "Successfully deleted extension."818 @authorize(logged_in)819 def vextensions(self):820 items=[]821 for extension in PbxVirtualExtension.query.filter_by(context=session['context']).all():822 items.append({'id': extension.id, 'extension': extension.extension, 'did': extension.did,823 'timeout': extension.timeout, 'pbx_route_id': extension.pbx_route_id})824 db.remove()825 out = dict({'identifier': 'id', 'label': 'extension', 'items': items})826 response = make_response(out)827 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]828 return response(request.environ, self.start_response)829 @authorize(logged_in)830 def vextension_add(self, **kw):831 schema = VirtualExtensionForm()832 try:833 form_result = schema.to_python(request.params)834 sve = PbxVirtualExtension()835 sve.extension = form_result.get('vextension_number')836 sve.did = form_result.get('vextension_did')837 sve.context = session['context']838 sve.timeout = form_result.get('timeout')839 sve.pbx_route_id = form_result.get('no_answer_destination')840 db.add(sve)841 db.commit(); db.flush()842 r = PbxRoute()843 r.context = session['context']844 r.domain = session['context']845 r.name = form_result.get('vextension_number')846 r.continue_route = True847 r.voicemail_enable = True848 r.voicemail_ext = form_result.get('vextension_number')849 r.pbx_route_type_id = 2850 r.pbx_to_id = sve.id851 db.add(r)852 db.commit(); db.flush()853 except validators.Invalid, error:854 return 'Validation Error: %s' % error855 db.remove()856 return "Successfully created virtual extension."857 @restrict("GET")858 @authorize(logged_in)859 def del_vext(self, **kw):860 try:861 delete_virtual_extension(request.params['extension'])862 except:863 return "Error deleting virtual extension."864 return "Successfully deleted virtual extension."865 @authorize(logged_in)866 def update_vext_grid(self, **kw):867 try:868 w = loads(urllib.unquote_plus(request.params.get("data")))869 for i in w['modified']:870 if not len(i['did']) == 10 or not str(i['did']).strip().isdigit():871 return "A virtual extension needs to be exactly 10 digits."872 ve = PbxVirtualExtension.query.filter_by(id=i['id']).filter_by(context=session['context']).first()873 ve.did = i['did']874 ve.timeout = i['timeout']875 ve.pbx_route_id = i['pbx_route_id']876 db.commit(); db.flush()877 except DataInputError, error:878 db.remove()879 return 'Error: %s' % error880 return "Successfully updated virtual extension."881 @authorize(logged_in)882 def vmboxes(self):883 items=[]884 for extension in PbxVirtualMailbox.query.filter_by(context=session['context']).all():885 items.append({'id': extension.id, 'extension': extension.extension, 'vm_password': extension.vm_password})886 db.remove()887 out = dict({'identifier': 'id', 'label': 'extension', 'items': items})888 response = make_response(out)889 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]890 return response(request.environ, self.start_response)891 @authorize(logged_in)892 def calling_rules(self):893 items=[]894 for rule in PbxCallingRule.query.all():895 items.append({'id': rule.id, 'name': rule.name})896 db.remove()897 out = dict({'identifier': 'id', 'label': 'name', 'items': items})898 response = make_response(out)899 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]900 return response(request.environ, self.start_response)901 @authorize(logged_in)902 def vmbox_by_id(self, id, **kw):903 items=[]904 extension = PbxVirtualMailbox.query.filter_by(context=session['context']).filter_by(id=id).first()905 items.append({'id': extension.id, 'extension': extension.extension, 'vm_password': extension.vm_password,906 'skip_greeting': extension.skip_greeting, 'audio_file': extension.audio_file,907 'vm_email': extension.vm_email, 'vm_attach_email': extension.vm_attach_email,908 'vm_notify_email': extension.vm_notify_email, 'vm_save': extension.vm_save})909 db.remove()910 out = dict({'identifier': 'id', 'label': 'extension', 'items': items})911 response = make_response(out)912 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]913 return response(request.environ, self.start_response)914 @authorize(logged_in)915 def vmbox_edit(self, **kw):916 schema = VirtualMailboxEditForm()917 try:918 form_result = schema.to_python(request.params)919 vm = PbxVirtualMailbox.query.filter_by(id=form_result.get('vmbox_id'))\920 .filter_by(context=session['context']).first()921 vm.vm_password = form_result.get('vm_password')922 vm.context = session['context']923 vm.skip_greeting = True if form_result.get('skip_greeting')=="true" else False924 vm.audio_file = form_result.get('audio_file', None)925 vm.vm_email = form_result.get('vm_email', None)926 vm.vm_password = form_result.get('vm_password', u'9999')927 vm.vm_attach_email = True if form_result.get('vm_attach_email')=="true" else False928 vm.vm_notify_email = True if form_result.get('vm_notify_email')=="true" else False929 vm.vm_save = True if form_result.get('vm_save')=="true" else False930 PbxRoute.query.filter_by(pbx_route_type_id=3).filter_by(pbx_to_id=vm.id).delete()931 db.commit(); db.flush()932 r = PbxRoute()933 r.context = session['context']934 r.domain = session['context']935 r.name = vm.extension936 r.continue_route = True937 r.voicemail_enable = True938 r.voicemail_ext = vm.extension939 r.pbx_route_type_id = 3940 r.pbx_to_id = vm.id941 db.add(r)942 db.commit(); db.flush()943 except validators.Invalid, error:944 return 'Validation Error: %s' % error945 db.remove()946 return "Successfully added virtual voicemail box."947 @authorize(logged_in)948 def vmbox_add(self, **kw):949 schema = VirtualMailboxForm()950 try:951 form_result = schema.to_python(request.params)952 vm = PbxVirtualMailbox()953 vm.extension = form_result.get('vmbox_number')954 vm.vm_password = form_result.get('vm_password')955 vm.context = session['context']956 vm.skip_greeting = True if form_result.get('skip_greeting')=="true" else False957 vm.audio_file = form_result.get('audio_file', None)958 vm.vm_email = form_result.get('vm_email', None)959 vm.vm_password = form_result.get('vm_password', u'9999')960 vm.vm_attach_email = True if form_result.get('vm_attach_email')=="true" else False961 vm.vm_notify_email = True if form_result.get('vm_notify_email')=="true" else False962 vm.vm_save = True if form_result.get('vm_save')=="true" else False963 db.add(vm)964 db.commit(); db.flush()965 r = PbxRoute()966 r.context = session['context']967 r.domain = session['context']968 r.name = form_result.get('vmbox_number')969 r.continue_route = True970 r.voicemail_enable = True971 r.voicemail_ext = form_result.get('vmbox_number')972 r.pbx_route_type_id = 3973 r.pbx_to_id = vm.id974 db.add(r)975 db.commit(); db.flush()976 except validators.Invalid, error:977 return 'Validation Error: %s' % error978 db.remove()979 return "Successfully added virtual voicemail box."980 @authorize(logged_in)981 def update_vmbox_grid(self, **kw):982 try:983 w = loads(urllib.unquote_plus(request.params.get("data")))984 for i in w['modified']:985 if not str(i['extension']).strip().isdigit() or not str(i['pin']).strip().isdigit():986 return "A virtual mailbox and pin needs to be exactly 3 or 4 numbers."987 vm = PbxVirtualMailbox.query.filter_by(id=i['id']).filter_by(context=session['context']).first()988 vm.vm_password = i['vm_password'].strip()989 db.commit(); db.flush()990 db.remove()991 except DataInputError, error:992 db.remove()993 return 'Error: %s' % error994 return "Successfully updated virtual mailbox."995 @restrict("GET")996 @authorize(logged_in)997 def del_vmbox(self, **kw):998 try:999 delete_virtual_mailbox(request.params['extension'])1000 except:1001 return "Error deleting virtual mailbox."1002 return "Successfully deleted virtual mailbox."1003 @authorize(logged_in)1004 def groups(self):1005 items=[]; members = []1006 for group in PbxGroup.query.filter_by(context=session['context']).all():1007 for extension in PbxGroupMember.query.filter_by(pbx_group_id=group.id).all():1008 members.append(extension.extension)1009 items.append({'id': group.id, 'name': group.name, 'ring_strategy': group.ring_strategy,1010 'no_answer_destination': group.no_answer_destination, 'members': ",".join(members),1011 'timeout': group.timeout})1012 members = []1013 db.remove()1014 out = dict({'identifier': 'id', 'label': 'name', 'items': items})1015 response = make_response(out)1016 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1017 return response(request.environ, self.start_response)1018 @authorize(logged_in)1019 def group_by_id(self, id, **kw):1020 items=[]; members=[]1021 group = PbxGroup.query.filter_by(context=session['context']).filter_by(id=id).first()1022 for extension in PbxGroupMember.query.filter_by(pbx_group_id=group.id).all():1023 members.append(extension.extension)1024 items.append({'id': group.id, 'name': group.name, 'ring_strategy': group.ring_strategy,1025 'no_answer_destination': group.no_answer_destination, 'members': ",".join(members),1026 'timeout': group.timeout})1027 db.remove()1028 out = dict({'identifier': 'id', 'label': 'name', 'items': items})1029 response = make_response(out)1030 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1031 return response(request.environ, self.start_response)1032 @authorize(logged_in)1033 def group_add(self, **kw):1034 schema = GroupForm()1035 try:1036 form_result = schema.to_python(request.params)1037 if len(form_result.get('group_extensions').split(","))==1:1038 return "Error: You need to have at least two extensions to make a group."1039 sg = PbxGroup()1040 sg.name = form_result.get('group_name')1041 sg.context = session['context']1042 sg.ring_strategy = form_result.get('group_ring_strategy', 'sim')1043 sg.no_answer_destination = form_result.get('no_answer_destination', None)1044 sg.timeout = form_result.get('timeout', 13)1045 db.add(sg)1046 db.commit(); db.flush()1047 if not form_result.get('group_extensions').split(","):1048 if not form_result.get('group_extensions').isdigit():1049 return "You need to have at least one extension to make a group."1050 else:1051 db.add(PbxGroupMember(sg.id, form_result.get('group_extensions')))1052 db.commit(); db.flush()1053 else:1054 for ext in form_result.get('group_extensions').split(","):1055 if not ext.isdigit():1056 continue1057 db.add(PbxGroupMember(sg.id, ext))1058 db.commit(); db.flush()1059 except validators.Invalid, error:1060 db.remove()1061 return 'Validation Error: %s' % error1062 r = PbxRoute()1063 r.context = session['context']1064 r.domain = session['context']1065 r.name = form_result.get('group_name')1066 r.continue_route = True1067 r.voicemail_enable = True1068 r.voicemail_ext = form_result.get('group_name')1069 r.pbx_route_type_id = 41070 r.pbx_to_id = sg.id1071 db.add(r)1072 db.commit(); db.flush()1073 db.remove()1074 return "Successfully added group "+str(form_result.get('group_name'))+"."1075 @authorize(logged_in)1076 def group_edit(self, **kw):1077 schema = GroupEditForm()1078 try:1079 form_result = schema.to_python(request.params)1080 if len(form_result.get('group_extensions').split(","))==1:1081 return "Error: You need to have at least two extensions to make a group."1082 db.delete(PbxGroup.query.filter_by(id=form_result.get('group_id')).first())1083 for member in PbxGroupMember.query.filter_by(pbx_group_id=form_result.get('group_id')).all():1084 db.delete(member)1085 db.delete(PbxRoute.query.filter_by(pbx_route_type_id=4).filter_by(pbx_to_id=form_result.get('group_id')).first())1086 db.commit(); db.flush()1087 sg = PbxGroup()1088 sg.name = form_result.get('group_name')1089 sg.context = session['context']1090 sg.ring_strategy = form_result.get('group_ring_strategy', 'sim')1091 sg.no_answer_destination = form_result.get('no_answer_destination', None)1092 sg.timeout = form_result.get('timeout', 13)1093 db.add(sg)1094 db.commit(); db.flush()1095 if not form_result.get('group_extensions').split(","):1096 if not form_result.get('group_extensions').isdigit():1097 return "You need to have at least one extension to make a group."1098 else:1099 db.add(PbxGroupMember(sg.id, form_result.get('group_extensions')))1100 db.commit()1101 db.flush()1102 else:1103 for ext in form_result.get('group_extensions').split(","):1104 if not ext.isdigit():1105 continue1106 db.add(PbxGroupMember(sg.id, ext))1107 db.commit()1108 db.flush()1109 except validators.Invalid, error:1110 db.remove()1111 return 'Validation Error: %s' % error1112 r = PbxRoute()1113 r.context = session['context']1114 r.domain = session['context']1115 r.name = form_result.get('group_name')1116 r.continue_route = True1117 r.voicemail_enable = True1118 r.voicemail_ext = form_result.get('group_name')1119 r.pbx_route_type_id = 41120 r.pbx_to_id = sg.id1121 db.add(r)1122 db.commit(); db.flush()1123 db.remove()1124 return "Successfully added group "+str(form_result.get('group_name'))+"."1125 @authorize(logged_in)1126 def update_group_grid(self, **kw):1127 w = loads(urllib.unquote_plus(request.params.get("data")))1128 try:1129 for i in w['modified']:1130 g = PbxGroup.query.filter_by(id=i['id']).first()1131 g.no_answer_destination = i['no_answer_destination']1132 g.ring_strategy = i['ring_strategy']1133 db.commit(); db.flush()1134 PbxGroupMember.query.filter(PbxGroupMember.pbx_group_id==i['id']).delete()1135 for gm in i['members'].split(","):1136 if not gm.strip().isdigit():1137 continue1138 db.add(PbxGroupMember(i['id'], gm.strip()))1139 db.commit()1140 db.flush()1141 except:1142 db.remove()1143 return "Error updating group."1144 return "Successfully updated group."1145 @restrict("GET")1146 @authorize(logged_in)1147 def del_group(self, **kw):1148 try:1149 delete_group(request.params['name'])1150 except:1151 return "Error"1152 return "Successfully deleted group."1153 @authorize(logged_in)1154 def dids(self):1155 items=[]1156 for did in PbxDid.query.filter_by(context=session['context']).all():1157 route = db.query(PbxRoute.id, PbxRouteType.name, PbxRoute.name)\1158 .join(PbxRouteType).filter(PbxRoute.context==session['context']).filter(PbxRoute.id==did.pbx_route_id).first()1159 if route:1160 items.append({'id': did.id, 'did': did.did, 'route_name': route[1]+': '+route[2], 'pbx_route_id': route.id})1161 else:1162 items.append({'id': did.id, 'did': did.did, 'route_name': "Broken Route!", 'pbx_route_id': 0})1163 lbid = get_route_labels_ids()1164 db.remove()1165 out = dict({'identifier': 'id', 'label': 'name', 'items': items,'did_labels': lbid[0], 'did_ids': lbid[1]})1166 response = make_response(out)1167 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1168 return response(request.environ, self.start_response)1169 @authorize(logged_in)1170 def update_did_grid(self, **kw):1171 w = loads(urllib.unquote_plus(request.params.get("data")))1172 try:1173 for i in w['modified']:1174 sd = PbxDid.query.filter_by(id=i['id']).filter_by(context=session['context']).first()1175 sd.pbx_route_id = i['route_name']1176 db.commit()1177 db.commit(); db.flush()1178 except:1179 db.remove()1180 return "Error updating DID."1181 return "Successfully updated DID."1182 @authorize(logged_in)1183 def faxes(self):1184 files = []1185 dir = fs_vm_dir+session['context']+"/faxes"1186 try:1187 for i in os.listdir(dir):1188 if not i.endswith(".png"):1189 continue1190 path = dir+"/"+i1191 uuid = i.split("_")[0].strip()1192 name = i.split("_")[1].strip().split(".")[0]1193 if name.find("-") == -1:1194 page_num = "Single Page"1195 else:1196 page_num = name.split("-")[1].split(".")[0].strip()1197 name = name.split("-")[0].strip()1198 page_num = int(page_num)+11199 tpath = "/vm/" +session['context']+"/faxes/"+i1200 received = str(modification_date(path)).strip("\"")1201 fsize = str(os.path.getsize(path))1202 row = PbxCdr.query.filter(PbxCdr.uuid==uuid).first()1203 if row:1204 caller = row.caller_id_number[len(row.caller_id_number)-10:]1205 else:1206 caller = "Unknown"1207 files.append({'uuid': uuid, 'name': name, 'caller_id': caller, 'path': tpath, 'received': received, 'size': fsize, 'page_num': page_num})1208 except:1209 os.makedirs(dir)1210 db.remove()1211 out = dict({'identifier': 'path', 'label': 'name', 'items': files})1212 response = make_response(out)1213 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1214 return response(request.environ, self.start_response)1215 @authorize(logged_in)1216 def fax_add(self, **kw):1217 schema = FaxForm()1218 try:1219 form_result = schema.to_python(request.params)1220 sf = PbxFax()1221 sf.extension = form_result.get('fax_name')1222 sf.context = session['context']1223 db.add(sf)1224 db.commit(); db.flush()1225 r = PbxRoute()1226 r.context = session['context']1227 r.domain = session['context']1228 r.name = form_result.get('fax_name')1229 r.continue_route = False1230 r.voicemail_enable = False1231 r.voicemail_ext = form_result.get('fax_name')1232 r.pbx_route_type_id = 121233 r.pbx_to_id = sf.id1234 db.add(r)1235 db.commit(); db.flush()1236 except validators.Invalid, error:1237 db.remove()1238 return 'Validation Error: Please correct form inputs and resubmit.'1239 @authorize(logged_in)1240 def fax_ext(self):1241 items=[]1242 for ext in PbxFax.query.filter_by(context=session['context']).all():1243 items.append({'id': ext.id, 'extension': ext.extension})1244 db.remove()1245 out = dict({'identifier': 'id', 'label': 'extension', 'items': items})1246 response = make_response(out)1247 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1248 return response(request.environ, self.start_response)1249 @authorize(logged_in)1250 def fax_send(self, **kw):1251 form = cgi.FieldStorage()1252 user = User.query.filter_by(session_id=session.id).first()1253 if not user:1254 return1255 ep = db.execute("SELECT pbx_dids.did FROM pbx_dids "1256 "INNER JOIN pbx_routes on pbx_dids.pbx_route_id = pbx_routes.id "1257 "WHERE pbx_routes.pbx_route_type_id=12").fetchone()1258 if ep:1259 if len(ep[0])==10:1260 origination_caller_id_number = ep[0]1261 else:1262 origination_caller_id_number = ep[1]1263 else:1264 origination_caller_id_number = "0000000000"1265 myfile = request.params['uploadedfiles[]']1266 fname = myfile.filename.lstrip(os.sep)1267 ext = fname.split(".")[len(fname.split("."))-1]1268 if not ext:1269 return "Error no file type found."1270 fname = re.sub('[^A-Za-z0-9]+', '', fname)1271 fname = fname+"."+ext1272 try:1273 dir = "/tmp/"1274 permanent_file = open(os.path.join(dir,fname), 'w')1275 shutil.copyfileobj(myfile.file, permanent_file)1276 myfile.file.close()1277 permanent_file.close()1278 except:1279 return "Error uploading file. The administrator has been contacted."1280 converted = fname.split(".")[0]+".tiff"1281 call("convert -density 204x98 -units PixelsPerInch -resize 1728x1186\! -monochrome -compress Fax /tmp/"+fname+" /tmp/"+converted, shell=True)1282 os.remove("/tmp/"+fname)1283 con = ESLconnection(ESL_HOST, ESL_PORT, ESL_PASS)1284 if con.connected:1285 con.bgapi("originate", "{fax_ident='FreePyBX Web Fax',fax_header="+str(origination_caller_id_number)+",fax_enable_t38=true,origination_caller_id_number="+str(origination_caller_id_number)+"}sofia/gateway/voipinnovations/"+str(request.params["fax_recipient"])+" &txfax(/tmp/"+str(converted)+")")1286 @restrict("GET")1287 @authorize(logged_in)1288 def del_fax(self, **kw):1289 """For security, we check the input, then put them into their own context"""1290 file_name = request.params['name'].split("/")[len(request.params['name'].split("/"))-1]1291 try:1292 dir = fs_vm_dir+session['context']+"/faxes/"+file_name1293 os.remove(dir)1294 except:1295 return "Error deleting fax."1296 return "Deleted fax."1297 @authorize(logged_in)1298 def del_fax_ext(self, **kw):1299 try:1300 delete_fax_ext(request.params['name'])1301 except:1302 return "Error deleting fax extension."1303 return "Successfully deleted fax extension."1304 @authorize(logged_in)1305 def tod_routes(self):1306 items=[]1307 for tod in PbxTODRoute.query.filter_by(context=session['context']).all():1308 route_match = db.query(PbxRoute.id, PbxRouteType.name, PbxRoute.name)\1309 .join(PbxRouteType).filter(PbxRoute.context==session['context']).filter(PbxRoute.id==tod.match_route_id).first()1310 route_nomatch = db.query(PbxRoute.id, PbxRouteType.name, PbxRoute.name)\1311 .join(PbxRouteType).filter(PbxRoute.context==session['context']).filter(PbxRoute.id==tod.nomatch_route_id).first()1312 items.append({'id': tod.id, 'name': tod.name, 'day_start': tod.day_start, 'day_end': tod.day_end, 'time_start': tod.time_start[1:len(tod.time_start)-3], 'time_end': tod.time_end[1:len(tod.time_end)-3],1313 'match_route_id': tod.match_route_id, 'nomatch_route_id': tod.nomatch_route_id, 'match_name': route_match[1]+': '+route_match[2],1314 'match_id': route_match[0], 'nomatch_name': route_nomatch[1]+': '+route_nomatch[2], 'nomatch_id': route_nomatch[0]})1315 db.remove()1316 out = dict({'identifier': 'id', 'label': 'extension', 'items': items})1317 response = make_response(out)1318 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1319 return response(request.environ, self.start_response)1320 @authorize(logged_in)1321 def tod_route_add(self, **kw):1322 schema = TODForm()1323 try:1324 form_result = schema.to_python(request.params)1325 t = PbxTODRoute()1326 t.domain = session['context']1327 t.context = session['context']1328 t.name = form_result.get('name')1329 t.day_start = form_result.get('day_start')1330 t.day_end = form_result.get('day_end')1331 t.time_start = form_result.get('time_start')1332 t.time_end = form_result.get('time_end')1333 t.match_route_id = form_result.get('match_route_id')1334 t.nomatch_route_id = form_result.get('nomatch_route_id')1335 db.add(t)1336 db.commit(); db.flush()1337 r = PbxRoute()1338 r.context = session['context']1339 r.domain = session['context']1340 r.name = form_result.get('name')1341 r.continue_route = True1342 r.voicemail_enable = True1343 r.voicemail_ext = form_result.get('name')1344 r.pbx_route_type_id = 61345 r.pbx_to_id = t.id1346 db.add(r)1347 db.commit(); db.flush()1348 except validators.Invalid, error:1349 return 'Error: %s' % error1350 db.remove()1351 return "Successfully added time of day route."1352 @authorize(logged_in)1353 def tod_by_id(self, id, **kw):1354 items=[]1355 row = PbxTODRoute.query.filter_by(id=id).filter_by(context=session['context']).first()1356 items.append({'id': row.id, 'name': row.name, 'day_start': row.day_start,1357 'day_end': row.day_end, 'time_start': row.time_start, 'time_end': row.time_end,1358 'match_route_id': row.match_route_id, 'nomatch_route_id': row.nomatch_route_id})1359 out = dict({'identifier': 'id', 'label': 'name', 'items': items})1360 response = make_response(out)1361 response.headers = [("Content-type", 'application/json'),]1362 return response(request.environ, self.start_response)1363 @authorize(logged_in)1364 def edit_tod(self, **kw):1365 try:1366 tod = PbxTODRoute.query.filter_by(context=session['context'])\1367 .filter(PbxTODRoute.id==request.params.get('tod_id')).first()1368 if not tod:1369 return "Error: No route found with that id."1370 tod.name = request.params.get('name')1371 tod.store_id = request.params.get('store_id')1372 tod.day_start = request.params.get('day_start')1373 tod.day_end = request.params.get('day_end')1374 tod.time_start = request.params.get('time_start')1375 tod.time_end = request.params.get('time_end')1376 tod.active = True if request.params.get('active')=="true" else False1377 tod.match_route_id = request.params.get('match_route_id')1378 tod.nomatch_route_id = request.params.get('nomatch_route_id')1379 db.commit(); db.flush()1380 db.remove()1381 except validators.Invalid, error:1382 db.remove()1383 return 'Error: %s' % error1384 return "Successfully updated time of day route."1385 @restrict("GET")1386 @authorize(logged_in)1387 def del_tod(self, **kw):1388 try:1389 t = PbxTODRoute.query.filter(PbxTODRoute.id==request.params['id']).first()1390 delete_tod(t.name)1391 except:1392 return "Error deleting Time of Day Route"1393 return "Successfully deleted Time of Day Route."1394 @authorize(logged_in)1395 def recordings(self):1396 files = []1397 dir = fs_vm_dir+session['context']+"/recordings/"1398 try:1399 for i in os.listdir(dir):1400 files.append(generateFileObject(i, "", dir))1401 except:1402 os.makedirs(dir)1403 out = dict({'identifier': 'name', 'label': 'name', 'items': files})1404 response = make_response(out)1405 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1406 return response(request.environ, self.start_response)1407 @authorize(logged_in)1408 def audio_recordings(self):1409 items = []1410 dir = fs_vm_dir+session['context']+"/recordings/"1411 try:1412 for i in os.listdir(dir):1413 fo = generateFileObject(i, "", dir)1414 items.append({'id': '1,'+fo["name"], 'name': 'Recording: '+fo["name"] , 'data': fo["path"], 'type': 1, 'real_id': ""})1415 db.remove()1416 except:1417 pass1418 out = dict({'identifier': 'id', 'label': 'name', 'items': items})1419 response = make_response(out)1420 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1421 return response(request.environ, self.start_response)1422 @restrict("POST")1423 @authorize(logged_in)1424 def delete_recording(self, **kw):1425 t = PbxIVR.query.filter(PbxIVR.data==request.params['name']).filter(PbxIVR.context==session['context']).first()1426 if t:1427 return "Error: Recording "+request.params['name']+" is in use by IVR named "+t.name+"!"1428 try:1429 dir = fs_vm_dir+session['context']+"/recordings/"+request.params['name']1430 os.remove(dir)1431 except:1432 db.remove()1433 return "Error deleting recording."1434 db.remove()1435 return "Deleted recording."1436 @authorize(logged_in)1437 def upload_recording(self):1438 myfile = request.params['uploadedfiles[]']1439 if not myfile.filename.endswith(".wav"):1440 return "Error uploading file. File must have .wav extension."1441 try:1442 dir = fs_vm_dir + "/"+session['context']+"/recordings/"1443 permanent_file = open(os.path.join(dir,myfile.filename.lstrip(os.sep)), 'w')1444 shutil.copyfileobj(myfile.file, permanent_file)1445 myfile.file.close()1446 permanent_file.close()1447 except:1448 return "Error uploading file. The administrator has been contacted."1449 return "Successfully uploaded recording."1450 @authorize(logged_in)1451 def recording_name(self, **kw):1452 files = []1453 dir = fs_vm_dir+session['context']+"/recordings/"1454 old_name = request.params['old_name']1455 new_name = request.params['new_name']1456 src = dir+old_name1457 dst = dir+new_name1458 if not new_name.endswith(".wav"):1459 dst +=".wav"1460 os.rename(src, dst)1461 return "Successfully renamed recording"1462 @authorize(logged_in)1463 def conferences(self):1464 items=[]1465 for conf in PbxConferenceBridge.query.filter_by(context=session['context']).all():1466 items.append({'id': conf.id, 'extension': conf.extension, 'pin': conf.pin})1467 db.remove()1468 out = dict({'identifier': 'id', 'label': 'extension', 'items': items})1469 response = make_response(out)1470 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1471 return response(request.environ, self.start_response)1472 @authorize(logged_in)1473 def conf_add(self, **kw):1474 schema = ConferenceForm()1475 try:1476 form_result = schema.to_python(request.params)1477 sc = PbxConferenceBridge()1478 sc.extension = form_result.get('extension')1479 sc.pin = form_result.get('pin')1480 sc.context = session['context']1481 sc.domain = session['context']1482 db.add(sc)1483 db.commit(); db.flush()1484 except validators.Invalid, error:1485 db.remove()1486 return 'Validation Error: %s' % error1487 r = PbxRoute()1488 r.context = session['context']1489 r.domain = session['context']1490 r.name = form_result.get('extension')1491 r.continue_route = False1492 r.voicemail_enable = False1493 r.voicemail_ext = form_result.get('extension')1494 r.pbx_route_type_id = 71495 r.pbx_to_id = sc.id1496 db.add(r)1497 db.commit(); db.flush()1498 db.remove()1499 return "Successfully added conference bridge."1500 @restrict("GET")1501 @authorize(logged_in)1502 def del_conf(self, **kw):1503 try:1504 delete_conf(request.params['extension'])1505 except:1506 return "Error deleting conference bridge."1507 return "Successfully deleted conference bridge."1508 @authorize(logged_in)1509 def cid_routes(self):1510 items=[]1511 for cid in PbxCallerIDRoute.query.filter_by(context=session['context']).all():1512 route = db.query(PbxRoute.id, PbxRouteType.name, PbxRoute.name)\1513 .join(PbxRouteType).filter(PbxRoute.context==session['context']).filter(PbxRoute.id==cid.pbx_route_id).first()1514 items.append({'id': cid.id, 'cid_number': cid.cid_number, 'pbx_route_id': cid.pbx_route_id, 'pbx_route_name': route[1]+': '+route[2]})1515 db.remove()1516 out = dict({'identifier': 'id', 'label': 'cid_number', 'items': items})1517 response = make_response(out)1518 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1519 return response(request.environ, self.start_response)1520 @authorize(logged_in)1521 def cid_add(self, **kw):1522 schema = CIDForm()1523 try:1524 form_result = schema.to_python(request.params)1525 sc = PbxCallerIDRoute()1526 sc.cid_number = form_result.get('cid_number')1527 sc.pbx_route_id = form_result.get('pbx_route_id')1528 sc.context = session['context']1529 sc.domain = session['context']1530 db.add(sc)1531 db.commit(); db.flush()1532 except validators.Invalid, error:1533 db.remove()1534 return 'Validation Error: %s' % error1535 db.remove()1536 return "Successfully added Caller ID Route."1537 @restrict("GET")1538 @authorize(logged_in)1539 def del_cid(self, **kw):1540 try:1541 delete_cid(request.params['cid_number'])1542 except:1543 return "Error deleting CallerID Route."1544 return "Successfully deleted CallerID route."1545 @authorize(logged_in)1546 def blacklisted(self):1547 items=[]1548 for cid in PbxBlacklistedNumber.query.filter_by(context=session['context']).all():1549 items.append({'id': cid.id, 'cid_number': cid.cid_number})1550 members = []1551 db.remove()1552 out = dict({'identifier': 'id', 'label': 'cid_number', 'items': items})1553 response = make_response(out)1554 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1555 return response(request.environ, self.start_response)1556 @authorize(logged_in)1557 def blacklist_add(self, **kw):1558 schema = PbxBlacklistedForm()1559 try:1560 form_result = schema.to_python(request.params)1561 sc = PbxBlacklistedNumber()1562 sc.cid_number = form_result.get('cid_number')1563 sc.context = session['context']1564 sc.domain = session['context']1565 db.add(sc)1566 db.commit(); db.flush()1567 except validators.Invalid, error:1568 db.remove()1569 return 'Validation Error: %s' % error1570 db.remove()1571 return "Successfully added to blacklist."1572 @restrict("GET")1573 @authorize(logged_in)1574 def del_bl(self, **kw):1575 try:1576 del_blacklist(request.params['cid_number'])1577 except:1578 return "Error deleting blacklisted number."1579 return "Successfully deleted blacklisted number."1580 @authorize(logged_in)1581 def tts(self):1582 items=[]1583 for row in PbxTTS.query.filter_by(context=session['context']).all():1584 items.append({'id': row.id, 'name': row.name, 'text': row.text})1585 db.remove()1586 out = dict({'identifier': 'id', 'label': 'name', 'items': items})1587 response = make_response(out)1588 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1589 return response(request.environ, self.start_response)1590 @authorize(logged_in)1591 def tts_add(self, **kw):1592 schema = TTSForm()1593 try:1594 form_result = schema.to_python(request.params)1595 t = PbxTTS()1596 t.name = form_result.get('name')1597 t.text = form_result.get('text')1598 t.context = session['context']1599 t.domain = session['context']1600 t.voice = u'Allison'1601 db.add(t)1602 db.commit(); db.flush()1603 except validators.Invalid, error:1604 db.remove()1605 return 'Validation Error: %s' % error1606 db.remove()1607 return "Successfully added Text to Speech entry."1608 @authorize(logged_in)1609 def update_tts_grid(self, **kw):1610 try:1611 w = loads(urllib.unquote_plus(request.params.get("data")))1612 for i in w['modified']:1613 t = PbxTTS.query.filter_by(id=i['id']).filter_by(context=session['context']).first()1614 t.name = i['name'].strip()1615 t.text = i['text'].strip()1616 db.commit()1617 db.commit(); db.flush()1618 except DataInputError, error:1619 db.remove()1620 return 'Error: %s' % error1621 return "Successfully updated TTS entry."1622 @restrict("GET")1623 @authorize(logged_in)1624 def del_tts(self, **kw):1625 return delete_tts(request.params['name'])1626 @authorize(logged_in)1627 def ivr(self):1628 items=[]1629 for ivr in PbxIVR.query.filter_by(context=session['context']).all():1630 items.append({'id': ivr.id, 'name': ivr.name})1631 db.remove()1632 out = dict({'identifier': 'id', 'label': 'name', 'items': items})1633 response = make_response(out)1634 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1635 return response(request.environ, self.start_response)1636 @authorize(logged_in)1637 def ivr_by_id(self, id, **kw):1638 items=[]1639 for ivr in PbxIVR.query.filter_by(context=session['context']).filter_by(id=id).all():1640 options=[]1641 for opt in PbxIVROption.query.filter_by(pbx_ivr_id=ivr.id).all():1642 options.append({'option': opt.option, 'pbx_route_id': opt.pbx_route_id})1643 items.append({'id': ivr.id, 'name': ivr.name,'timeout': ivr.timeout, 'direct_dial': ivr.direct_dial, 'data': ivr.data,\1644 'audio_name': str(ivr.audio_type)+','+str(ivr.data), 'timeout_destination': ivr.timeout_destination, 'options': options})1645 db.remove()1646 out = dict({'identifier': 'id', 'label': 'name', 'items': items})1647 response = make_response(out)1648 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1649 return response(request.environ, self.start_response)1650 @authorize(logged_in)1651 def ivr_add(self, **kw):1652 schema = IVRForm()1653 try:1654 form_result = schema.to_python(request.params)1655 s = PbxIVR()1656 s.name = form_result.get('ivr_name')1657 s.audio_type = form_result.get('audio_name').split(",")[0].strip()1658 s.data = form_result.get('audio_name').split(",")[1].strip()1659 s.domain = session['context']1660 s.context = session['context']1661 s.timeout = form_result.get('timeout')1662 s.timeout_destination = form_result.get('timeout_destination')1663 if request.params.has_key('direct_dial'):1664 s.direct_dial = True1665 else:1666 s.direct_dial = False1667 db.add(s)1668 db.commit(); db.flush()1669 if len(form_result.get('option_1'))>0:1670 i = PbxIVROption()1671 i.option=11672 i.pbx_ivr_id = s.id1673 i.pbx_route_id = form_result.get('option_1')1674 db.add(i)1675 db.commit(); db.flush()1676 if len(form_result.get('option_2'))>0:1677 i = PbxIVROption()1678 i.option=21679 i.pbx_ivr_id = s.id1680 i.pbx_route_id = form_result.get('option_2')1681 db.add(i)1682 db.commit(); db.flush()1683 if len(form_result.get('option_3'))>0:1684 i = PbxIVROption()1685 i.option=31686 i.pbx_ivr_id = s.id1687 i.pbx_route_id = form_result.get('option_3')1688 db.add(i)1689 db.commit(); db.flush()1690 if len(form_result.get('option_4'))>0:1691 i = PbxIVROption()1692 i.option=41693 i.pbx_ivr_id = s.id1694 i.pbx_route_id = form_result.get('option_4')1695 db.add(i)1696 db.commit(); db.flush()1697 if len(form_result.get('option_5'))>0:1698 i = PbxIVROption()1699 i.option=51700 i.pbx_ivr_id = s.id1701 i.pbx_route_id = form_result.get('option_5')1702 db.add(i)1703 db.commit(); db.flush()1704 if len(form_result.get('option_6'))>0:1705 i = PbxIVROption()1706 i.option=61707 i.pbx_ivr_id = s.id1708 i.pbx_route_id = form_result.get('option_6')1709 db.add(i)1710 db.commit(); db.flush()1711 if len(form_result.get('option_7'))>0:1712 i = PbxIVROption()1713 i.option=71714 i.pbx_ivr_id = s.id1715 i.pbx_route_id = form_result.get('option_7')1716 db.add(i)1717 db.commit(); db.flush()1718 if len(form_result.get('option_8'))>0:1719 i = PbxIVROption()1720 i.option=81721 i.pbx_ivr_id = s.id1722 i.pbx_route_id = form_result.get('option_8')1723 db.add(i)1724 db.commit(); db.flush()1725 if len(form_result.get('option_9'))>0:1726 i = PbxIVROption()1727 i.option=91728 i.pbx_ivr_id = s.id1729 i.pbx_route_id = form_result.get('option_9')1730 db.add(i)1731 db.commit(); db.flush()1732 if len(form_result.get('option_0'))>0:1733 i = PbxIVROption()1734 i.option=01735 i.pbx_ivr_id = s.id1736 i.pbx_route_id = form_result.get('option_0')1737 db.add(i)1738 db.commit(); db.flush()1739 except validators.Invalid, error:1740 db.remove()1741 return 'Validation Error: Please correct form inputs and resubmit.'1742 r = PbxRoute()1743 r.context = session['context']1744 r.domain = session['context']1745 r.name = form_result.get('ivr_name')1746 r.continue_route = True1747 r.voicemail_enable = True1748 r.voicemail_ext = form_result.get('ivr_name')1749 r.pbx_route_type_id = 51750 r.pbx_to_id = s.id1751 db.add(r)1752 db.commit(); db.flush()1753 db.remove()1754 return "Successfully added IVR."1755 @authorize(logged_in)1756 def ivr_edit(self, **kw):1757 schema = IVREditForm()1758 try:1759 form_result = schema.to_python(request.params)1760 s = PbxIVR.query.filter_by(id=form_result.get('ivr_id')).filter_by(context=session['context']).first()1761 s.audio_type = form_result.get('audio_name').split(",")[0].strip()1762 s.data = form_result.get('audio_name').split(",")[1].strip()1763 s.domain = session['context']1764 s.context = session['context']1765 s.timeout = form_result.get('timeout')1766 s.timeout_destination=form_result.get('timeout_destination')1767 if request.params.has_key('direct_dial'):1768 s.direct_dial=True1769 else:1770 s.direct_dial=False1771 db.commit(); db.flush()1772 PbxIVROption.query.filter_by(pbx_ivr_id=s.id).delete()1773 db.commit(); db.flush()1774 if len(form_result.get('option_1'))>0:1775 i = PbxIVROption()1776 i.option=11777 i.pbx_ivr_id=s.id1778 i.pbx_route_id=form_result.get('option_1')1779 db.add(i)1780 db.commit(); db.flush()1781 if len(form_result.get('option_2'))>0:1782 i = PbxIVROption()1783 i.option=21784 i.pbx_ivr_id=s.id1785 i.pbx_route_id=form_result.get('option_2')1786 db.add(i)1787 db.commit(); db.flush()1788 if len(form_result.get('option_3'))>0:1789 i = PbxIVROption()1790 i.option=31791 i.pbx_ivr_id=s.id1792 i.pbx_route_id=form_result.get('option_3')1793 db.add(i)1794 db.commit(); db.flush()1795 if len(form_result.get('option_4'))>0:1796 i = PbxIVROption()1797 i.option=41798 i.pbx_ivr_id=s.id1799 i.pbx_route_id=form_result.get('option_4')1800 db.add(i)1801 db.commit(); db.flush()1802 if len(form_result.get('option_5'))>0:1803 i = PbxIVROption()1804 i.option=51805 i.pbx_ivr_id=s.id1806 i.pbx_route_id=form_result.get('option_5')1807 db.add(i)1808 db.commit(); db.flush()1809 if len(form_result.get('option_6'))>0:1810 i = PbxIVROption()1811 i.option=61812 i.pbx_ivr_id=s.id1813 i.pbx_route_id=form_result.get('option_6')1814 db.add(i)1815 db.commit(); db.flush()1816 if len(form_result.get('option_7'))>0:1817 i = PbxIVROption()1818 i.option=71819 i.pbx_ivr_id=s.id1820 i.pbx_route_id=form_result.get('option_7')1821 db.add(i)1822 db.commit(); db.flush()1823 if len(form_result.get('option_8'))>0:1824 i = PbxIVROption()1825 i.option=81826 i.pbx_ivr_id=s.id1827 i.pbx_route_id=form_result.get('option_8')1828 db.add(i)1829 db.commit(); db.flush()1830 if len(form_result.get('option_9'))>0:1831 i = PbxIVROption()1832 i.option=91833 i.pbx_ivr_id=s.id1834 i.pbx_route_id=form_result.get('option_9')1835 db.add(i)1836 db.commit(); db.flush()1837 if len(form_result.get('option_0'))>0:1838 i = PbxIVROption()1839 i.option=01840 i.pbx_ivr_id=s.id1841 i.pbx_route_id=form_result.get('option_0')1842 db.add(i)1843 db.commit(); db.flush()1844 except validators.Invalid, error:1845 db.remove()1846 return 'Validation Error: Please correct form inputs and resubmit.'1847 db.remove()1848 return "Successfully edited IVR."1849 @authorize(logged_in)1850 def update_ivr_grid(self, **kw):1851 w = loads(urllib.unquote_plus(request.params.get("data")))1852 for i in w['modified']:1853 ivr = PbxIVR.query.filter_by(context=session['context']).filter(PbxIVR.id==int(i['id'])).first()1854 ivr.name = i['name']1855 route = PbxRoute.query.filter_by(context=session['context']).\1856 filter(PbxRoute.pbx_route_type_id==5).filter(PbxRoute.pbx_to_id==int(i['id'])).first()1857 route.name = i['name']1858 db.commit(); db.flush()1859 db.remove()1860 return "Successfully updated IVR."1861 @restrict("GET")1862 @authorize(logged_in)1863 def del_ivr(self, **kw):1864 return delete_ivr(request.params['name'])1865 @authorize(logged_in)1866 def ivr_audio(self):1867 items = []1868 dir = fs_vm_dir+session['context']+"/recordings/"1869 try:1870 for i in os.listdir(dir):1871 fo = generateFileObject(i, "", dir)1872 items.append({'id': '1,'+fo["name"], 'name': 'Recording: '+fo["name"] , 'data': fo["path"], 'type': 1, 'real_id': ""})1873 except:1874 os.makedirs(dir)1875 for row in PbxTTS.query.filter_by(context=session['context']).all():1876 items.append({'id': '2,'+str(row.id), 'name': 'TTS: '+row.name, 'data': row.text, 'type': 2, 'real_id': row.id})1877 db.remove()1878 out = dict({'identifier': 'id', 'label': 'name', 'items': items})1879 response = make_response(out)1880 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1881 return response(request.environ, self.start_response)1882 @authorize(logged_in)1883 def voicemail_from_file_system(self):1884 files = []1885 dir = fs_vm_dir+session['context']+"/"+session['ext']1886 try:1887 for i in os.listdir(dir):1888 if i.startswith("greeting_"):1889 continue1890 id = i.split("_")[1].split(".")[0].strip()1891 row = PbxCdr.query.filter(PbxCdr.uuid==id).first()1892 path = dir+"/"+i1893 tpath = "/vm/"+session['context']+"/"+session['ext']+"/"+i1894 received = str(modification_date(path)).strip("\"")1895 fsize = str(os.path.getsize(path))1896 caller = row.caller_id_number[len(row.caller_id_number)-10:]1897 files.append({'name': caller, 'path': tpath, 'received': received, 'size': fsize})1898 except:1899 os.makedirs(dir)1900 out = dict({'identifier': 'path', 'label': 'name', 'items': files})1901 response = make_response(out)1902 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1903 return response(request.environ, self.start_response)1904 @authorize(logged_in)1905 def voicemail(self):1906 items=[]1907 path = []1908 i = 41909 if session['group_id'] > 1:1910 rows = VoiceMail.query.filter_by(domain=session['context']).filter(VoiceMail.username==session['ext']).all()1911 else:1912 rows = VoiceMail.query.filter_by(domain=session['context']).all()1913 for row in rows:1914 received = time.strftime("%a, %d %b %Y %H:%M", time.localtime(row.created_epoch))1915 name = row.cid_number[len(row.cid_number)-10:]1916 fname = row.file_path.split("/")[len(row.file_path.split("/"))-1]1917 for x in range(1,5):1918 path.append(row.file_path.split("/")[len(row.file_path.split("/"))-i])1919 i=i-11920 i = 41921 fpath = "/"+"/".join(path)1922 path = []1923 items.append({'name': name, 'to': row.username, 'received': received, 'path': fpath, 'size': row.message_len})1924 db.remove()1925 out = dict({'identifier': 'path', 'label': 'name', 'items': items})1926 response = make_response(out)1927 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1928 return response(request.environ, self.start_response)1929 @restrict("POST")1930 @authorize(logged_in)1931 def delete_voicemail(self, **kw):1932 path = request.params['data']1933 file_name = path.split("/")[len(path.split("/"))-1]1934 uuid = file_name.split("_")[1].split(".")[0].strip()1935 try:1936 VoiceMail.query.filter(VoiceMail.uuid==uuid).filter(VoiceMail.username==session['ext']).delete()1937 dir = fs_vm_dir+"/"+session['context']+"/"+session['ext']1938 os.remove(os.path.join(dir, file_name))1939 except:1940 return "Error: Virtual Extension voicemail can be deleted by dialing * plus extension from a registered endpoint."1941 return "Deleted voicemail."1942 @authorize(logged_in)1943 def cdr(self):1944 items=[]1945 for row in PbxCdr.query.filter_by(context=session['context']).order_by(desc(PbxCdr.id)).all():1946 num = row.caller_id_number if len(row.caller_id_number)<=10 else row.caller_id_number[len(row.caller_id_number)-10:]1947 items.append({'id': row.id, 'caller_id_name': row.caller_id_name, 'caller_id_number': num,1948 'destination_number': row.destination_number, 'start_stamp': fix_date(row.start_stamp), 'answer_stamp': fix_date(row.answer_stamp),1949 'end_stamp': fix_date(row.end_stamp), 'duration': row.duration, 'billsec':row.billsec, 'hangup_cause': row.hangup_cause})1950 db.remove()1951 out = dict({'identifier': 'id', 'label': 'caller_id_number', 'items': items})1952 response = make_response(out)1953 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1954 return response(request.environ, self.start_response)1955 @authorize(logged_in)1956 def cdr_summary(self):1957 items=[]1958 sdate = request.params.get("sdate", 'TIMESTAMP')1959 edate = request.params.get("edate", 'CURRENT_TIMESTAMP')1960 sdate = "TIMESTAMP '"+sdate+"'" if sdate != 'TIMESTAMP' else "CURRENT_TIMESTAMP - INTERVAL '1 MONTH'"1961 edate = "TIMESTAMP '"+edate+"' + interval '1 day'" if edate != 'CURRENT_TIMESTAMP' else 'CURRENT_TIMESTAMP'1962 for row in db.execute("SELECT * "1963 "FROM cdr "1964 "WHERE customer_id = :customer_id "1965 "AND bleg_uuid IS NOT NULL "1966 "AND cdr.start_stamp > "+sdate+" AND cdr.end_stamp < "+edate+" "1967 "ORDER BY start_stamp DESC", {'customer_id': str(session['customer_id'])}).fetchall():1968 num = row.caller_id_number if len(row.caller_id_number)<=10 else row.caller_id_number[len(row.caller_id_number)-10:]1969 items.append({'id': row.id, 'caller_id_name': row.caller_id_name, 'caller_id_number': num,1970 'destination_number': row.destination_number, 'start_stamp': fix_date(row.start_stamp), 'answer_stamp': fix_date(row.answer_stamp),1971 'end_stamp': fix_date(row.end_stamp), 'duration': row.duration, 'billsec':row.billsec, 'hangup_cause': row.hangup_cause})1972 db.remove()1973 out = dict({'identifier': 'id', 'label': 'caller_id_number', 'items': items})1974 response = make_response(out)1975 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]1976 return response(request.environ, self.start_response)1977 @authorize(logged_in)1978 def cdr_ext_summary(self):1979 items=[]1980 sdate = request.params.get("sdate", 'TIMESTAMP')1981 edate = request.params.get("edate", 'CURRENT_TIMESTAMP')1982 sdate = "TIMESTAMP '"+sdate+"'" if sdate != 'TIMESTAMP' else "TIMESTAMP '"+datetime.today().strftime("%m/%d/%Y 12:00:00 AM")+"'"1983 edate = "TIMESTAMP '"+edate+"' + interval '1 day'" if edate != 'CURRENT_TIMESTAMP' else 'CURRENT_TIMESTAMP'1984 for row in db.execute("SELECT DISTINCT users.id, users.first_name ||' '|| users.last_name AS agent, users.portal_extension as extension, "1985 "(SELECT COUNT(uuid) FROM cdr WHERE (cdr.caller_id_number = users.portal_extension or cdr.destination_number = users.portal_extension) "1986 "AND cdr.start_stamp > "+sdate+" AND cdr.end_stamp < "+edate+" AND call_direction = 'inbound' AND cdr.context = customers.context) AS call_count_in, "1987 "(SELECT COUNT(uuid) FROM cdr WHERE (cdr.caller_id_number = users.portal_extension or cdr.destination_number = users.portal_extension) "1988 "AND cdr.start_stamp > "+sdate+" AND cdr.end_stamp < "+edate+" AND call_direction = 'outbound' AND cdr.context = customers.context) AS call_count_out, "1989 "(SELECT coalesce(sum(billsec),0) FROM cdr WHERE (cdr.caller_id_number = users.portal_extension or cdr.destination_number = users.portal_extension) "1990 "AND cdr.start_stamp > "+sdate+" AND cdr.end_stamp < "+edate+" AND call_direction = 'inbound' AND cdr.context = customers.context) AS time_on_call_in, "1991 "(SELECT coalesce(sum(billsec),0) FROM cdr WHERE (cdr.caller_id_number = users.portal_extension or cdr.destination_number = users.portal_extension) "1992 "AND cdr.start_stamp > "+sdate+" AND cdr.end_stamp < "+edate+" AND call_direction = 'outbound' AND cdr.context = customers.context) AS time_on_call_out "1993 "FROM users "1994 "INNER JOIN customers ON customers.id = users.customer_id "1995 "WHERE customers.id = :customer_id "1996 "ORDER BY extension", {'customer_id': session['customer_id']}).fetchall():1997 m, s = divmod(row.time_on_call_in, 60)1998 h, m = divmod(m, 60)1999 toci = "%dh:%02dm:%02ds" % (h, m, s)2000 m, s = divmod(row.time_on_call_out, 60)2001 h, m = divmod(m, 60)2002 toco = "%dh:%02dm:%02ds" % (h, m, s)2003 items.append({'id': row.id, 'agent': row.agent, 'extension': row.extension, 'call_count_in': row.call_count_in,2004 'qstring': '?ext='+row.extension+'&sdate='+request.params.get("sdate", 'TIMESTAMP')+'&edate='+request.params.get("edate", 'CURRENT_TIMESTAMP'),2005 'call_count_out': row.call_count_out, 'time_on_call_in': toci, 'time_on_call_out': toco,2006 'from': request.params.get("sdate", 'TIMESTAMP') if request.params.get("sdate", 'TIMESTAMP') != 'TIMESTAMP' else datetime.today().strftime("%m/%d/%Y"),2007 'to': request.params.get("edate", 'CURRENT_TIMESTAMP') if request.params.get("edate", 'CURRENT_TIMESTAMP') != 'CURRENT_TIMESTAMP' else datetime.today().strftime("%m/%d/%Y")})2008 db.remove()2009 out = dict({'identifier': 'id', 'label': 'agent', 'items': items})2010 response = make_response(out)2011 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2012 return response(request.environ, self.start_response)2013 def cdr_ext(self):2014 items=[]2015 sdate = request.params.get("sdate", 'TIMESTAMP')2016 edate = request.params.get("edate", 'CURRENT_TIMESTAMP')2017 ext = request.params.get("ext")2018 sdate = "TIMESTAMP '"+sdate+"'" if sdate != 'TIMESTAMP' else "TIMESTAMP '"+datetime.today().strftime("%m/%d/%Y 12:00:00 AM")+"'"2019 edate = "TIMESTAMP '"+edate+"' + interval '1 day'" if edate != 'CURRENT_TIMESTAMP' else 'CURRENT_TIMESTAMP'2020 for row in db.execute("SELECT cdr.id AS id, caller_id_name, caller_id_number, destination_number, start_stamp, answer_stamp, "2021 "end_stamp, duration, billsec, hangup_cause "2022 "FROM cdr "2023 "INNER JOIN customers ON cdr.context = customers.context "2024 "WHERE customers.id = :customer_id "2025 "AND cdr.start_stamp > "+sdate+" AND cdr.end_stamp < "+edate+" "2026 "AND cdr.call_direction IS NOT NULL "2027 "AND (cdr.caller_id_number = :extension or cdr.destination_number = :extension) "2028 "ORDER BY id", {'customer_id': session['customer_id'], 'extension': ext}).fetchall():2029 num = row.caller_id_number if len(row.caller_id_number)<=10 else row.caller_id_number[len(row.caller_id_number)-10:]2030 items.append({'id': row.id, 'caller_id_name': row.caller_id_name, 'caller_id_number': num,2031 'destination_number': row.destination_number, 'start_stamp': fix_date(row.start_stamp), 'answer_stamp': fix_date(row.answer_stamp),2032 'end_stamp': fix_date(row.end_stamp), 'duration': row.duration, 'billsec':row.billsec, 'hangup_cause': row.hangup_cause})2033 db.remove()2034 out = dict({'identifier': 'id', 'label': 'caller_id_number', 'items': items})2035 response = make_response(out)2036 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2037 return response(request.environ, self.start_response)2038 @authorize(logged_in)2039 def cdr_ext_download(self):2040 items=[]2041 start = request.params.get("sdate")2042 end = request.params.get("edate")2043 sdate = request.params.get("sdate", 'TIMESTAMP')2044 edate = request.params.get("edate", 'CURRENT_TIMESTAMP')2045 ext = request.params.get("ext")2046 sdate = "TIMESTAMP '"+sdate+"'" if sdate != 'TIMESTAMP' else "TIMESTAMP '"+datetime.today().strftime("%m/%d/%Y 12:00:00 AM")+"'"2047 edate = "TIMESTAMP '"+edate+"' + interval '1 day'" if edate != 'CURRENT_TIMESTAMP' else 'CURRENT_TIMESTAMP'2048 for row in db.execute("SELECT cdr.id AS id, caller_id_name, caller_id_number, destination_number, start_stamp, answer_stamp, "2049 "end_stamp, duration, billsec, hangup_cause "2050 "FROM cdr "2051 "INNER JOIN customers ON cdr.context = customers.context "2052 "WHERE customers.id = :customer_id "2053 "AND cdr.start_stamp > "+sdate+" AND cdr.end_stamp < "+edate+" "2054 "AND cdr.call_direction IS NOT NULL "2055 "AND (cdr.caller_id_number = :extension or cdr.destination_number = :extension) "2056 "ORDER BY id", {'customer_id': session['customer_id'], 'extension': ext}).fetchall():2057 num = row.caller_id_number if len(row.caller_id_number)<=10 else row.caller_id_number[len(row.caller_id_number)-10:]2058 items.append({'id': row.id, 'caller_id_name': row.caller_id_name, 'caller_id_number': num,2059 'destination_number': row.destination_number, 'start_stamp': fix_date(row.start_stamp), 'answer_stamp': fix_date(row.answer_stamp),2060 'end_stamp': fix_date(row.end_stamp), 'duration': row.duration, 'billsec':row.billsec, 'hangup_cause': row.hangup_cause})2061 db.remove()2062 f = open("/tmp/Report_ext"+ext+".csv", "wb+")2063 csv_file = csv.writer(f)2064 #f=csv.writer(open("/tmp/Report_ext"+ext+".csv",'wb+'))2065 csv_file.writerow(["Name","Number","Destination","Start Time","End Time", "Duration Seconds","Hangup Cause"])2066 for csv_items in items:2067 csv_file.writerow([csv_items['caller_id_name'], csv_items['caller_id_number'], csv_items['destination_number'], csv_items['start_stamp'], csv_items['duration'], csv_items['hangup_cause']])2068 f.close()2069 size = os.path.getsize("/tmp/Report_ext"+ext+".csv")2070 response = make_file_response("/tmp/Report_ext"+ext+".csv")2071 response.headers = [("Content-type", "application/octet-stream"),2072 ("Content-Disposition", "attachment; filename="+"Report_ext"+ext+".csv"),2073 ("Content-length", str(size)),]2074 return response(request.environ, self.start_response)2075 @authorize(logged_in)2076 def customer_by_id(self, **kw):2077 items=[]2078 row = Customer.query.filter(Customer.id==session['customer_id']).first()2079 items.append({'id': row.id, 'name': row.name, 'email': row.email, 'address': row.address, 'address_2': row.address_2,2080 'city': row.city, 'state': row.state, 'zip': row.zip,2081 'tel': row.tel, 'url': row.url, 'active': row.active, 'context': row.context, 'has_crm': row.has_crm,2082 'has_call_center': row.has_call_center, 'contact_name': row.contact_name, 'contact_phone': row.contact_phone,2083 'contact_mobile': row.contact_mobile, 'contact_title': row.contact_title, 'contact_email': row.contact_email, 'notes': row.notes})2084 out = dict({'identifier': 'id', 'label': 'name', 'items': items})2085 response = make_response(out)2086 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2087 return response(request.environ, self.start_response)2088 @authorize(logged_in)2089 def edit_customer(self):2090 schema = CustomerForm()2091 try:2092 form_result = schema.to_python(request.params)2093 co = Customer.query.filter(Customer.id==session['customer_id']).first()2094 co.tel = form_result.get('tel')2095 co.address = form_result.get('address')2096 co.address_2 = form_result.get('address_2')2097 co.city = form_result.get('city')2098 co.state = form_result.get('state')2099 co.zip = form_result.get('zip')2100 co.url = form_result.get('url')2101 co.email = form_result.get('email')2102 co.contact_name = form_result.get('contact_name')2103 co.contact_phone = form_result.get('contact_phone')2104 co.contact_mobile = form_result.get('contact_mobile')2105 co.contact_title = form_result.get('contact_title')2106 co.contact_email = form_result.get('contact_email')2107 db.commit(); db.flush()2108 except validators.Invalid, error:2109 db.remove()2110 return 'Error: %s' % error2111 return "Successfully edited customer."2112 @authorize(logged_in)2113 def avail_findme_endpoints(self):2114 items=[]2115 for row in PbxEndpoint.query.filter_by(user_context=session['context']).order_by(PbxEndpoint.auth_id).all():2116 if PbxFindMeRoute.query.filter_by(pbx_endpoint_id=row.id).count()>0:2117 continue2118 items.append({'id': row.id, 'auth_id': row.auth_id})2119 db.remove()2120 out = dict({'identifier': 'id', 'label': 'auth_id', 'items': items})2121 response = make_response(out)2122 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2123 return response(request.environ, self.start_response)2124 @authorize(logged_in)2125 def inuse_findme_endpoints(self):2126 items=[]2127 for row in db.query(PbxFindMeRoute.id, PbxEndpoint.auth_id)\2128 .select_from(join(PbxFindMeRoute, PbxEndpoint, PbxEndpoint.pbx_find_me))\2129 .filter(PbxEndpoint.user_context==session['context']).all():2130 items.append({'id': row.id, 'auth_id': row.auth_id})2131 db.remove()2132 out = dict({'identifier': 'id', 'label': 'auth_id', 'items': items})2133 response = make_response(out)2134 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2135 return response(request.environ, self.start_response)2136 @authorize(logged_in)2137 def routes(self):2138 items=[]2139 for row in db.execute("SELECT sr.id, sr.name AS data, sr.pbx_to_id AS to_id, sr.pbx_route_type_id AS type_id, srt.name|| ': ' ||sr.name AS name "2140 "FROM pbx_routes sr "2141 "INNER JOIN pbx_route_types srt ON sr.pbx_route_type_id = srt.id "2142 "WHERE sr.context = :context", {'context': session['context']}):2143 items.append({'id': row.id, 'data': row.data, 'to_id': row.to_id, 'type_id': row.type_id, 'name': row.name})2144 db.remove()2145 out = dict({'identifier': 'id', 'label': 'name', 'items': items})2146 response = make_response(out)2147 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2148 return response(request.environ, self.start_response)2149 @jsonify2150 @authorize(logged_in)2151 def route_id_names(self):2152 return db.query(PbxRoute.name, PbxRoute.id).filter_by(context=session['context']).all()2153 @jsonify2154 @authorize(logged_in)2155 def route_ids(self):2156 names=[]2157 ids=[]2158 for r in db.query(PbxRoute.name, PbxRoute.id).filter_by(context=session['context']).order_by(PbxRoute.name).all():2159 names.append(r.name)2160 ids.append(r.id)2161 return dict({'names': names, 'ids': ids})2162 @authorize(logged_in)2163 def call_stats(self):2164 items=[]2165 volume=[]2166 ttime=[]2167 minimumt = 02168 maximumt = 02169 minimumv = 02170 maximumv = 102171 for row in User.query.filter(User.customer_id==session['customer_id']).all():2172 if not len(row.portal_extension):2173 continue2174 else:2175 extension = row.portal_extension2176 vol = get_volume(extension)2177 tt = get_talk_time(extension)2178 if vol > maximumv:2179 maximumv = vol2180 if tt > maximumt:2181 maximumt = tt2182 volume.append({'x': row.first_name+' '+row.last_name, 'y': vol})2183 ttime.append({'x': row.first_name+' '+row.last_name, 'y': tt})2184 items.append({'id': row.id, 'extension': extension, 'name': row.first_name+' '+row.last_name, 'volume': vol, 'talk_time': tt})2185 db.remove()2186 out = dict({'identifier': 'id', 'label': 'name', 'items': items, 'mint': minimumt,2187 'maxt': maximumt, 'minv': minimumv, 'maxv': maximumv, 'volume': volume, 'talk_time': ttime})2188 response = make_response(out)2189 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2190 return response(request.environ, self.start_response)2191 @authorize(logged_in)2192 def get_find_me_edit(self, id, **kw):2193 c.findme = db.query(PbxFindMeRoute.id,PbxFindMeRoute.ring_strategy, PbxFindMeRoute.destination_1, PbxFindMeRoute.destination_2,\2194 PbxFindMeRoute.destination_3, PbxFindMeRoute.destination_4, PbxEndpoint.auth_id)\2195 .select_from(join(PbxFindMeRoute, PbxEndpoint, PbxEndpoint.pbx_find_me))\2196 .filter(PbxEndpoint.user_context==session['context'])\2197 .filter_by(id=id).first()2198 db.remove()2199 return render('find_me_edit.html')2200 @authorize(credential('pbx_admin'))2201 def permissions(self, id, **kw):2202 c.findme = db.query(PbxFindMeRoute.id,PbxFindMeRoute.ring_strategy, PbxFindMeRoute.destination_1, PbxFindMeRoute.destination_2,\2203 PbxFindMeRoute.destination_3, PbxFindMeRoute.destination_4, PbxEndpoint.auth_id)\2204 .select_from(join(PbxFindMeRoute, PbxEndpoint, PbxEndpoint.pbx_find_me))\2205 .filter(PbxEndpoint.user_context==session['context'])\2206 .filter_by(id=id).first()2207 db.remove()2208 return render('find_me_edit.html')2209 @authorize(logged_in)2210 def names_user_ids(self):2211 names=[]2212 user_ids=[]2213 for row in User.query.filter_by(customer_id=session['customer_id']).all():2214 names.append(row.first_name+' '+row.last_name)2215 user_ids.append(row.id)2216 db.remove()2217 out = dict({'names': names, 'user_ids': user_ids})2218 response = make_response(out)2219 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2220 return response(request.environ, self.start_response)2221 @authorize(logged_in)2222 def destinations(self):2223 items=[]2224 for row in PbxEndpoint.query.filter_by(user_context=session['context']).all():2225 items.append({'id': row.id, 'ext': row.auth_id})2226 db.remove()2227 out = dict({'identifier': 'ext', 'label': 'ext', 'items': items})2228 response = make_response(out)2229 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2230 return response(request.environ, self.start_response)2231 @authorize(logged_in)2232 def device_store(self):2233 items=[]2234 for row in db.query(PbxDeviceManufacturer.id, PbxDeviceManufacturer.name, PbxDeviceType.model,2235 PbxDeviceType.id).join(PbxDeviceType).order_by(PbxDeviceManufacturer.name).all():2236 items.append({'id': row[0], 'manufacturer': row[1], 'model': row[2], 'name': row[1]+ ': '+row[2], 'device_type_id': row[3]})2237 db.remove()2238 out = dict({'identifier': 'device_type_id', 'label': 'name', 'items': items})2239 response = make_response(out)2240 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2241 return response(request.environ, self.start_response)2242 @authorize(logged_in)2243 def login_ext(self, id):2244 items=[]2245 for row in PbxEndpoint.query.filter_by(user_context=session['context']).\2246 filter_by(user_id=id).order_by(PbxEndpoint.auth_id).all():2247 items.append({'id': row.id, 'extension': row.auth_id})2248 db.remove()2249 out = dict({'identifier': 'extension', 'label': 'extension', 'items': items})2250 response = make_response(out)2251 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2252 return response(request.environ, self.start_response)2253 @authorize(logged_in)2254 def help(self, id, **kw):2255 help = PbxHelp.query.filter(PbxHelp.category_id==id).first()2256 if help:2257 data = help.data2258 else:2259 data = "No help to display in this category."2260 db.remove()2261 out = dict({'help': data})2262 response = make_response(out)2263 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2264 return response(request.environ, self.start_response)2265 @authorize(logged_in)2266 def ext_recordings2(self):2267 files = []2268 dir = fs_vm_dir+session['context']+"/extension-recordings/"2269 try:2270 for i in os.listdir(dir):2271 id = i.split("_")[1].split("_")[0].strip()2272 direction = i.split("_")[2]2273 ext = i.split("_")[0]2274 row = PbxCdr.query.filter(PbxCdr.uuid==id).first()2275 if not row:2276 continue2277 path = dir+"/"+i2278 tpath = "/vm/"+session['context']+"/extension-recordings/"+i2279 received = str(modification_date(path)).strip("\"")2280 fsize = str(os.path.getsize(path))2281 caller = row.caller_id_number[len(row.caller_id_number)-10:]2282 dest = row.destination_number[len(row.destination_number)-10 if len(row.destination_number) > 10 else 0:]2283 files.append({'name': caller, 'dest': dest, 'path': tpath, 'received': received, 'size': fsize, 'extension': ext, 'id': id, 'direction': direction})2284 except Exception, e:2285 raise2286 out = dict({'identifier': 'id', 'label': 'name', 'items': files})2287 response = make_response(out)2288 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2289 return response(request.environ, self.start_response)2290 @authorize(logged_in)2291 def ext_recordings(self):2292 files = []2293 dir = fs_vm_dir+session['context']+"/extension-recordings/"2294 try:2295 for i in os.listdir(dir):2296 id = i.split("_")[1].split("_")[0].strip()2297 direction = i.split("_")[2]2298 ext = i.split("_")[0]2299 row = PbxCdr.query.filter(PbxCdr.uuid==id).first()2300 if not row:2301 continue2302 path = dir+"/"+i2303 tpath = "/vm/"+session['context']+"/extension-recordings/"+i2304 received = str(modification_date(path)).strip("\"")2305 fsize = str(os.path.getsize(path))2306 caller = row.caller_id_number[len(row.caller_id_number)-10:]2307 dest = row.destination_number[len(row.destination_number)-10 if len(row.destination_number) > 10 else 0:]2308 files.append({'name': caller, 'dest': dest, 'path': tpath, 'received': received, 'size': fsize, 'extension': ext, 'id': id, 'direction': direction})2309 except Exception, e:2310 raise2311 out = dict({'identifier': 'id', 'label': 'name', 'items': files})2312 response = make_response(out)2313 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2314 return response(request.environ, self.start_response)2315 @authorize(logged_in)2316 def active_tickets(self):2317 items=[]2318 for row in Ticket.query.filter_by(customer_id=session['customer_id']).filter(Ticket.ticket_status_id!=4).all():2319 items.append({'id': row.id, 'customer_id': row.customer_id, 'opened_by': row.opened_by,2320 'status': row.ticket_status_id, 'priority': row.ticket_priority_id,2321 'type': row.ticket_type_id, 'created': row.created.strftime("%m/%d/%Y %I:%M:%S %p"),2322 'expected_resolve_date': row.expected_resolve_date.strftime("%m/%d/%Y %I:%M:%S %p"),2323 'subject': row.subject, 'description': row.description})2324 db.remove()2325 out = dict({'identifier': 'id', 'label': 'id', 'items': items})2326 response = make_response(out)2327 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2328 return response(request.environ, self.start_response)2329 @authorize(logged_in)2330 def closed_tickets(self):2331 items=[]2332 for row in Ticket.query.filter_by(customer_id=session['customer_id']).filter(Ticket.ticket_status_id==4).all():2333 items.append({'id': row.id, 'customer_id': row.customer_id, 'opened_by': row.opened_by,2334 'status': row.ticket_status_id, 'priority': row.ticket_priority_id,2335 'type': row.ticket_type_id, 'created': row.created.strftime("%m/%d/%Y %I:%M:%S %p"),2336 'expected_resolve_date': row.expected_resolve_date.strftime("%m/%d/%Y %I:%M:%S %p"),2337 'subject': row.subject, 'description': row.description})2338 db.remove()2339 out = dict({'identifier': 'id', 'label': 'id', 'items': items})2340 response = make_response(out)2341 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2342 return response(request.environ, self.start_response)2343 @authorize(logged_in)2344 def internal_tickets(self):2345 items=[]2346 for row in Ticket.query.filter_by(customer_id=session['customer_id']).filter(Ticket.ticket_status_id==7).all():2347 items.append({'id': row.id, 'customer_id': row.customer_id, 'opened_by': row.opened_by,2348 'status': row.ticket_status_id, 'priority': row.ticket_priority_id,2349 'type': row.ticket_type_id, 'created': row.created.strftime("%m/%d/%Y %I:%M:%S %p"),2350 'expected_resolve_date': row.expected_resolve_date.strftime("%m/%d/%Y %I:%M:%S %p"),2351 'subject': row.subject, 'description': row.description})2352 db.remove()2353 out = dict({'identifier': 'id', 'label': 'id', 'items': items})2354 response = make_response(out)2355 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2356 return response(request.environ, self.start_response)2357 @authorize(logged_in)2358 def ticket_data(self):2359 ticket_status_id =[]2360 ticket_status_name =[]2361 ticket_type_id = []2362 ticket_type_name = []2363 ticket_priority_id = []2364 ticket_priority_name = []2365 opened_by_id = []2366 opened_by_name = []2367 for row in TicketStatus.query.all():2368 ticket_status_id.append(row.id)2369 ticket_status_name.append(row.name)2370 for row in TicketType.query.all():2371 ticket_type_id.append(row.id)2372 ticket_type_name.append(row.name)2373 for row in TicketPriority.query.all():2374 ticket_priority_id.append(row.id)2375 ticket_priority_name.append(row.name)2376 for row in User.query.filter_by(customer_id=session['customer_id']).all():2377 opened_by_id.append(row.id)2378 opened_by_name.append(row.first_name+' '+row.last_name)2379 db.remove()2380 out = dict({'ticket_status_names': ticket_status_name, 'ticket_status_ids': ticket_status_id,2381 'ticket_type_names': ticket_type_name, 'ticket_type_ids': ticket_type_id,2382 'ticket_priority_names': ticket_priority_name, 'ticket_priority_ids': ticket_priority_id,2383 'opened_by_names': opened_by_name, 'opened_by_ids': opened_by_id})2384 response = make_response(out)2385 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2386 return response(request.environ, self.start_response)2387 @authorize(logged_in)2388 def ticket_types(self):2389 items=[]2390 for row in TicketType.query.all():2391 items.append({'id': row.id, 'name': row.name, 'description': row.description})2392 db.remove()2393 out = dict({'identifier': 'id', 'label': 'name', 'items': items})2394 response = make_response(out)2395 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2396 return response(request.environ, self.start_response)2397 @authorize(logged_in)2398 def ticket_statuses(self):2399 items=[]2400 for row in TicketStatus.query.all():2401 items.append({'id': row.id, 'name': row.name, 'description': row.description})2402 db.remove()2403 out = dict({'identifier': 'id', 'label': 'name', 'items': items})2404 response = make_response(out)2405 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2406 return response(request.environ, self.start_response)2407 @authorize(logged_in)2408 def ticket_priorities(self):2409 items=[]2410 for row in TicketPriority.query.all():2411 items.append({'id': row.id, 'name': row.name, 'description': row.description})2412 db.remove()2413 out = dict({'identifier': 'id', 'label': 'name', 'items': items})2414 response = make_response(out)2415 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2416 return response(request.environ, self.start_response)2417 @authorize(logged_in)2418 def ticket_add(self, **kw):2419 schema = TicketForm()2420 try:2421 form_result = schema.to_python(request.params)2422 t = Ticket()2423 t.subject = form_result.get('subject')2424 t.description = form_result.get('description')2425 t.customer_id = session['customer_id']2426 t.opened_by = form_result.get('user_id')2427 t.ticket_status_id = form_result.get('status_id')2428 t.ticket_priority_id = form_result.get('priority_id')2429 t.ticket_type_id = form_result.get('type_id')2430 t.expected_resolution_date = form_result.get('expected_resolution_date')2431 db.add(t)2432 db.commit(); db.flush()2433 except validators.Invalid, error:2434 db.remove()2435 return 'Validation Error: %s' % error2436 db.remove()2437 return "Successfully added ticket."2438 @authorize(logged_in)2439 def update_ticket_grid(self, **kw):2440 w = loads(urllib.unquote_plus(request.params.get("data")))2441 for i in w['modified']:2442 ticket = Ticket.query.filter_by(id=i['id']).first()2443 ticket.ticket_status_id = int(i['status'])2444 ticket.ticket_type_id = int(i['type'])2445 ticket.ticket_priority_id = int(i['priority'])2446 db.commit(); db.flush()2447 db.remove()2448 return "Successfully updated ticket."2449 @authorize(logged_in)2450 def ticket_view_by_id(self, id):2451 items=[]2452 notes=[]2453 for row in Ticket.query.filter_by(customer_id=session['customer_id']).filter(Ticket.id==id).all():2454 for note in TicketNote.query.filter_by(ticket_id=row.id).all():2455 notes.append({'id': note.id, 'ticket_id': note.ticket_id, 'user_id': note.user_id,2456 'created': note.created.strftime("%m/%d/%Y %I:%M:%S %p"), 'subject': note.subject,2457 'description': note.description})2458 items.append({'id': row.id, 'customer_id': row.customer_id, 'opened_by': row.opened_by,2459 'status': row.ticket_status_id, 'priority': row.ticket_priority_id,2460 'type': row.ticket_type_id, 'created': row.created.strftime("%m/%d/%Y %I:%M:%S %p"),2461 'expected_resolve_date': row.expected_resolve_date.strftime("%m/%d/%Y %I:%M:%S %p"),2462 'subject': row.subject, 'description': row.description, 'notes': notes})2463 out = dict({'identifier': 'id', 'label': 'id', 'items': items})2464 response = make_response(out)2465 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2466 return response(request.environ, self.start_response)2467 @authorize(logged_in)2468 def ticket_notes_by_id(self, id):2469 items=[]2470 for note in TicketNote.query.filter_by(ticket_id=id).all():2471 items.append({'id': note.id, 'ticket_id': note.ticket_id, 'user_id': note.user_id,2472 'created': note.created.strftime("%m/%d/%Y %I:%M:%S %p"), 'subject': note.subject,2473 'description': note.description})2474 out = dict({'identifier': 'id', 'label': 'subject', 'items': items})2475 response = make_response(out)2476 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]2477 return response(request.environ, self.start_response)2478 @authorize(logged_in)2479 def add_ticket_note(self, **kw):2480 schema = TicketNoteForm()2481 try:2482 form_result = schema.to_python(request.params)2483 t = TicketNote()2484 t.ticket_id = form_result.get('ticket_note_id')2485 t.subject = form_result.get('ticket_subject')2486 t.description = form_result.get('ticket_note')2487 t.user_id = form_result.get('user_id')2488 db.add(t)2489 db.commit(); db.flush()2490 except validators.Invalid, error:2491 db.remove()2492 return 'Validation Error: %s' % error2493 db.remove()...

Full Screen

Full Screen

call_center.py

Source:call_center.py Github

copy

Full Screen

1""" This Source Code Form is subject to the terms of the Mozilla Public2 License, v. 2.0. If a copy of the MPL was not distributed with this3 file, You can obtain one at http://mozilla.org/MPL/2.0/.4 Software distributed under the License is distributed on an "AS IS"5 basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the6 License for the specific language governing rights and limitations7 under the License.8 The Original Code is FreePyBX/VoiceWARE.9 The Initial Developer of the Original Code is Noel Morgan,10 Copyright (c) 2011-2012 VoiceWARE Communications, Inc. All Rights Reserved.11 http://www.vwci.com/12 You may not remove or alter the substance of any license notices (including13 copyright notices, patent notices, disclaimers of warranty, or limitations14 of liability) contained within the Source Code Form of the Covered Software,15 except that You may alter any license notices to the extent required to16 remedy known factual inaccuracies."""17import logging18from datetime import datetime19from pylons import request, response, session, config, tmpl_context as c, url20from pylons.controllers.util import abort, redirect21from freepybx.lib.base import BaseController, render22from freepybx.model import meta23from freepybx.model.meta import *24from freepybx.lib.util import *25from itertools import chain26from genshi import HTML27from pylons.decorators.rest import restrict28from genshi import HTML29import formencode30from formencode import validators31from freepybx.lib.pymap.imap import Pymap32from freepybx.lib.auth import *33from freepybx.lib.validators import *34from decorator import decorator35from pylons.decorators.rest import restrict36import formencode37from formencode import validators38from pylons.decorators import validate39from simplejson import loads, dumps40from webob import Request, Response41import simplejson as json42import transaction43import pprint44import os, sys45from stat import *46from webob import Request, Response47import cgi48import simplejson as json49from simplejson import loads, dumps50import os, sys51import simplejson as json52from simplejson import loads, dumps53import urllib, urllib254from freepybx.model import meta55from freepybx.model.meta import *56from freepybx.model.meta import Session as db57import cgitb; cgitb.enable()58logged_in = IsLoggedIn()59log = logging.getLogger(__name__)60DEBUG=False61fs_vm_dir = config['app_conf']['fs_vm_dir']62ESL_HOST = config['app_conf']['esl_host']63ESL_PORT = config['app_conf']['esl_port']64ESL_PASS = config['app_conf']['esl_pass']65class DataInputError(Exception):66 message=""67 def __init__(self, message=None):68 Exception.__init__(self, message or self.message)69class CallCenterController(BaseController):70 @authorize(logged_in)71 def queues(self):72 items=[]73 for queue in CallCenterQueue.query.filter_by(context=session['context']).all():74 items.append({'id': queue.id, 'name': queue.name})75 out = dict({'identifier': 'name', 'label': 'name', 'items': items})76 response = make_response(out)77 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]78 return response(request.environ, self.start_response)79 @authorize(logged_in)80 def ccq_add(self):81 schema = QueueForm()82 try:83 form_result = schema.to_python(request.params)84 ccq = CallCenterQueue()85 ccq.name = form_result['name']86 ccq.context = session['context']87 ccq.domain = session['context']88 ccq.audio_type = form_result.get('audio_name').split(",")[0]89 ccq.audio_name = form_result.get('audio_name').split(",")[1]90 ccq.moh_sound = form_result.get('moh_sound', 'local_stream://moh')91 ccq.time_base_score = form_result.get('time_base_score', 'system')92 ccq.max_wait_time = form_result.get('max_wait_time', 0)93 ccq.max_wait_time_with_no_agent = form_result.get('max_wait_time_with_no_agent', 0)94 ccq.max_wait_time_with_no_agent_reached = form_result.get('max_wait_time_with_no_agent_reached', 5)95 ccq.tier_rules_apply = form_result.get('tier_rules_apply', False)96 ccq.tier_rule_wait_second = form_result.get('tier_rule_wait_second', 300)97 ccq.tier_rule_wait_multiply_level = form_result.get('tier_rule_wait_multiply_level', False)98 ccq.tier_rule_agent_no_wait = form_result.get('tier_rule_agent_no_wait', False)99 ccq.discard_abandoned_after = form_result.get('discard_abandoned_after', 1800)100 ccq.abandoned_resume_allowed = form_result.get('abandoned_resume_allowed', False)101 ccq.strategy = form_result.get('strategy', 'callback')102 ccq.failed_route_id = form_result.get('failed_route_id', 0)103 ccq.record_calls = form_result.get('record_calls', False)104 ccq.announce_position = form_result.get('announce_position', False)105 ccq.announce_sound = form_result.get('announce_sound').split(",")[1]106 ccq.announce_frequency = form_result.get('announce_frequency')107 db.add(ccq)108 db.commit()109 db.flush()110 dir = fs_vm_dir+session['context']+"/queue-recordings/"+ccq.name111 if not os.path.exists(dir):112 os.makedirs(dir)113 except validators.Invalid, error:114 db.remove()115 return 'Error: %s.' % error116 r = PbxRoute()117 r.context = session['context']118 r.domain = session['context']119 r.name = form_result['name']120 r.continue_route = True121 r.voicemail_enable = True122 r.voicemail_ext = form_result['name']123 r.pbx_route_type_id = 10124 r.pbx_to_id = ccq.id125 db.add(r)126 db.commit()127 db.flush()128 db.remove()129 return "Successfully added Call Center queue "+form_result['name']+"."130 @authorize(logged_in)131 def ccq_edit(self):132 schema = QueueEditForm()133 try:134 form_result = schema.to_python(request.params)135 ccq = CallCenterQueue.query.filter_by(context=session['context']).filter_by(id=form_result.get('ccq_id')).first()136 ccq.context = session['context']137 ccq.domain = session['context']138 ccq.audio_type = form_result.get('audio_name').split(",")[0]139 ccq.audio_name = form_result.get('audio_name').split(",")[1]140 ccq.moh_sound = form_result.get('moh_sound', 'local_stream://moh')141 ccq.time_base_score = form_result.get('time_base_score', 'system')142 ccq.max_wait_time = form_result.get('max_wait_time', 0)143 ccq.max_wait_time_with_no_agent = form_result.get('max_wait_time_with_no_agent', 0)144 ccq.max_wait_time_with_no_agent_reached = form_result.get('max_wait_time_with_no_agent_reached', 5)145 ccq.tier_rules_apply = form_result.get('tier_rules_apply', False)146 ccq.tier_rule_wait_second = form_result.get('tier_rule_wait_second', 300)147 ccq.tier_rule_wait_multiply_level = form_result.get('tier_rule_wait_multiply_level', False)148 ccq.tier_rule_agent_no_wait = form_result.get('tier_rule_agent_no_wait', False)149 ccq.discard_abandoned_after = form_result.get('discard_abandoned_after', 1800)150 ccq.abandoned_resume_allowed = form_result.get('abandoned_resume_allowed', False)151 ccq.strategy = form_result.get('strategy')152 ccq.failed_route_id = form_result.get('failed_route_id', 0)153 ccq.record_calls = form_result.get('record_calls', False)154 ccq.announce_position = form_result.get('announce_position', False)155 ccq.announce_sound = form_result.get('announce_sound').split(",")[1]156 ccq.announce_frequency = form_result.get('announce_frequency')157 db.commit()158 db.flush()159 except validators.Invalid, error:160 db.remove()161 return 'Error: %s.' % error162 db.remove()163 return "Successfully updated Call Center queue "+ccq.name+"."164 def ccq_by_id(self, id, **kw):165 items=[]166 for ccq in CallCenterQueue.query.filter_by(context=session['context']).filter_by(id=id).all():167 items.append({'id': ccq.id, 'name': ccq.name, 'audio_type': ccq.audio_type, 'audio_name': str(ccq.audio_type)+","+str(ccq.audio_name),168 'moh_sound': ccq.moh_sound, 'time_base_score': ccq.time_base_score, 'max_wait_time': ccq.max_wait_time,169 'max_wait_time_with_no_agent': ccq.max_wait_time_with_no_agent, 'max_wait_time_with_no_agent_reached': ccq.max_wait_time_with_no_agent_reached,170 'tier_rules_apply': ccq.tier_rules_apply, 'tier_rule_wait_second': ccq.tier_rule_wait_second, 'tier_rule_wait_multiply_level': ccq.tier_rule_wait_multiply_level,171 'tier_rule_agent_no_wait': ccq.tier_rule_agent_no_wait, 'discard_abandoned_after': ccq.discard_abandoned_after,172 'abandoned_resume_allowed': ccq.abandoned_resume_allowed, 'strategy': ccq.strategy, 'failed_route_id': ccq.failed_route_id,173 'record_calls': ccq.record_calls, 'announce_position': ccq.announce_position, 'announce_sound': "1,"+ccq.announce_sound,174 'announce_frequency': ccq.announce_frequency})175 out = dict({'identifier': 'id', 'label': 'name', 'items': items})176 response = make_response(out)177 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]178 return response(request.environ, self.start_response)179 @authorize(logged_in)180 def ccq_audio(self):181 items = []182 dir = fs_vm_dir+session['context']+"/recordings/"183 for i in os.listdir(dir):184 fo = generateFileObject(i, "", dir)185 items.append({'id': '1,'+fo["name"], 'name': 'Recording: '+fo["name"] , 'data': fo["path"], 'type': 1, 'real_id': ""})186 items.append({'id': '0,local_stream://moh', 'name': 'Default Music on Hold' , 'data': 'local_stream://moh', 'type': 1, 'real_id': ""})187 out = dict({'identifier': 'id', 'label': 'name', 'items': items})188 response = make_response(out)189 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]190 return response(request.environ, self.start_response)191 @authorize(logged_in)192 def delete_queue(self, **kw):193 id = request.params.get('id', None)194 q = CallCenterQueue.query.filter(CallCenterQueue.id==id).filter(CallCenterQueue.context==session['context']).first()195 queue = CallCenterQueue.query.filter(CallCenterQueue.id==q.id).first()196 CallCenterTier.query.filter(CallCenterTier.queue_id==queue.id).delete()197 CallCenterQueue.query.filter(CallCenterQueue.id==q.id).delete()198 db.commit()199 db.flush()200 db.remove()201 return "Successfully removed queue."202 @authorize(logged_in)203 def agents(self):204 items=[]205 for agent in CallCenterAgent.query.filter_by(context=session['context']).all():206 items.append({'id': agent.id, 'extension': agent.extension, 'status': agent.status})207 out = dict({'identifier': 'extension', 'label': 'extension', 'items': items})208 response = make_response(out)209 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]210 return response(request.environ, self.start_response)211 @authorize(logged_in)212 def agent_avail_endpoints(self):213 items=[]214 ext = request.params.get('ext', None)215 if ext:216 items.append({'id': 0, 'extension': ext})217 for row in PbxEndpoint.query.filter_by(user_context=session['context']).order_by(PbxEndpoint.auth_id).all():218 if CallCenterAgent.query.filter_by(extension=row.auth_id).filter_by(context=session['context']).count()>0:219 continue220 items.append({'id': row.id, 'extension': row.auth_id})221 out = dict({'identifier': 'extension', 'label': 'extension', 'items': items})222 response = make_response(out)223 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]224 return response(request.environ, self.start_response)225 @authorize(logged_in)226 def agent_endpoints(self):227 items=[]228 for row in PbxEndpoint.query.filter_by(user_context=session['context']).order_by(PbxEndpoint.auth_id).all():229 items.append({'id': row.id, 'extension': row.auth_id})230 out = dict({'identifier': 'extension', 'label': 'extension', 'items': items})231 response = make_response(out)232 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]233 return response(request.environ, self.start_response)234 @authorize(logged_in)235 def agent_add(self):236 schema = AgentForm()237 try:238 form_result = schema.to_python(request.params)239 cca = CallCenterAgent()240 cca.extension = form_result.get('extension')241 e = PbxEndpoint.query.filter_by(user_context=session['context']).filter(PbxEndpoint.auth_id==cca.extension).first()242 cca.context = session['context']243 cca.domain = session['context']244 cca.type = 'callback'245 cca.system = 'single_box'246 cca.name = cca.extension+"@"+session['context']247 cca.timeout = form_result.get('timeout', 30)248 cca.contact = "[call_timeout="+cca.timeout+"]user/"+cca.name249 cca.max_no_answer = form_result.get('max_no_answer', 3)250 cca.wrap_up_time = form_result.get('wrap_up_time', 30)251 cca.reject_delay_time = form_result.get('reject_delay_time', 30)252 cca.busy_delay_time = form_result.get('busy_delay_time', 0)253 cca.no_answer_delay_time = form_result.get('no_answer_delay_time', 5)254 cca.record_calls = form_result.get('record_calls', 0)255 cca.status = 'Available'256 cca.state = 'Waiting'257 cca.user_id = e.user_id258 cca.pbx_endpoint_id = e.id259 db.add(cca)260 db.commit()261 db.flush()262 except validators.Invalid, error:263 db.remove()264 return 'Error: %s.' % error265 db.remove()266 return "Successfully added agent."267 @authorize(logged_in)268 def agent_edit(self):269 schema = AgentEditForm()270 try:271 form_result = schema.to_python(request.params)272 cca = CallCenterAgent.query.filter_by(context=session['context']).filter(CallCenterAgent.id==form_result.get('agent_id')).first()273 cca.extension = form_result.get('extension')274 e = PbxEndpoint.query.filter_by(user_context=session['context']).filter(PbxEndpoint.auth_id==cca.extension).first()275 cca.context = session['context']276 cca.domain = session['context']277 cca.type = 'callback'278 cca.record_calls = form_result.get('record_calls', 0)279 cca.timeout = form_result.get('timeout', 30)280 cca.max_no_answer = form_result.get('max_no_answer', 3)281 cca.wrap_up_time = form_result.get('wrap_up_time', 30)282 cca.reject_delay_time = form_result.get('reject_delay_time', 30)283 cca.busy_delay_time = form_result.get('busy_delay_time', 0)284 cca.no_answer_delay_time = form_result.get('no_answer_delay_time', 5)285 cca.user_id = e.user_id286 cca.pbx_endpoint_id = e.id287 db.commit()288 db.flush()289 except validators.Invalid, error:290 db.remove()291 return 'Error: %s.' % error292 db.remove()293 return "Successfully edited agent."294 @restrict("GET")295 @authorize(logged_in)296 def del_agent(self, **kw):297 try:298 CallCenterAgent.query.filter_by(id=request.params.get('id', 0)).delete()299 db.commit()300 db.flush()301 db.remove()302 except:303 return "Error deleting agent."304 return "Successfully deleted agent."305 def cca_by_id(self, id, **kw):306 items=[]307 for cca in CallCenterAgent.query.filter_by(context=session['context']).filter_by(id=id).all():308 items.append({'id': cca.id, 'extension': cca.extension, 'type': cca.type, 'timeout': cca.timeout,309 'max_no_answer': cca.max_no_answer, 'wrap_up_time': cca.wrap_up_time, 'reject_delay_time': cca.reject_delay_time,310 'busy_delay_time': cca.busy_delay_time, 'no_answer_delay_time': cca.no_answer_delay_time, 'record_calls': cca.record_calls})311 out = dict({'identifier': 'id', 'label': 'name', 'items': items})312 response = make_response(out)313 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]314 return response(request.environ, self.start_response)315 @authorize(logged_in)316 def update_agent_grid(self):317 try:318 w = loads(urllib.unquote_plus(request.params.get("data")))319 for i in w['modified']:320 log.debug(w['modified'])321 fsa = CallCenterAgent.query.filter(CallCenterAgent.name==str(i['extension'])+"@"+str(session['context'])).first()322 fsa.status = i['status']323 db.commit()324 db.flush()325 db.remove()326 except DataInputError, error:327 return 'Error: %s' % error328 return "Successfully update agent."329 @authorize(logged_in)330 def tiers(self):331 items=[]332 for tier in CallCenterTier.query.join(CallCenterQueue).filter(CallCenterQueue.context==session['context']).all():333 agent = get_agent(tier.agent_id)334 queue = get_queue(tier.queue_id)335 items.append({'id': tier.id, 'agent': agent.extension, 'queue': queue.name, 'level': tier.level, 'position': tier.position, 'state': tier.state})336 out = dict({'identifier': 'id', 'label': 'agent', 'items': items})337 response = make_response(out)338 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]339 return response(request.environ, self.start_response)340 @authorize(logged_in)341 def tier_add(self):342 schema = TierForm()343 try:344 form_result = schema.to_python(request.params)345 log.debug("######################" + form_result.get('queue_name'))346 cca = CallCenterAgent.query.filter_by(extension=form_result.get('agent_extension', None)).filter_by(context=session['context']).first()347 cur_cct = CallCenterTier.query.filter_by(agent=cca.name).first()348 ccq = CallCenterQueue.query.filter_by(name=form_result.get('queue_name', None)).first()349 if cur_cct:350 return "Agent in tier already exists!"351 cct = CallCenterTier()352 cct.extension = cca.extension353 cct.queue_id = ccq.id354 cct.agent_id = cca.id355 cct.queue = str(ccq.name)+"@"+session['context']356 cct.agent = str(cca.extension)+"@"+session['context']357 cct.level = form_result.get('level', 1)358 cct.state = 'Ready'359 cct.position = form_result.get('position', 1)360 cct.context = session['context']361 cct.domain = session['context']362 db.add(cct)363 db.commit()364 db.flush()365 except validators.Invalid, error:366 db.remove()367 return 'Error: %s.' % error368 db.remove()369 return "Successfully created tier agent."370 @authorize(logged_in)371 def update_tier_grid(self):372 try:373 w = loads(urllib.unquote_plus(request.params.get("data")))374 for i in w['modified']:375 log.debug(w['modified'])376 tier = CallCenterTier.query.filter_by(id=i['id']).first()377 tier.state = i['state']378 tier.level = i['level']379 tier.position = i['position']380 db.commit()381 db.flush()382 db.remove()383 except DataInputError, error:384 return 'Error: %s' % error385 return "Sucessfully updated agent tiers."386 @restrict("GET")387 @authorize(logged_in)388 def del_tier(self, **kw):389 try:390 CallCenterTier.query.filter_by(id=request.params.get('id', 0)).delete()391 db.commit()392 db.flush()393 db.remove()394 except:395 return "Error deleting tier agent."396 return "Successfully deleted tier agent."397 def cc_cdr_stats(self):398 pass399 def get_queue_calls(self):400 log.debug(request.params.get("sid"))401 user = User.query.filter_by(session_id=request.params.get("sid")).first()402 if user:403 context = user.get_context()404 else:405 return ""406 items = []407 sql = "SELECT * FROM call_center_callers WHERE queue like '%@{0}'".format(context)408 for call in db.execute(sql):409 items.append({'queue': call.queue.split("@")[0], 'cid_name': call.cid_name, 'cid_number': call.cid_number, 'agent': call.serving_agent.split("@")[0], 'state': call.state, 'uuid': call.uuid})410 if not len(items) == 0:411 return ""412 out = items413 response = make_response(out)414 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]415 return response(request.environ, self.start_response)416 @restrict("POST")417 @authorize(logged_in)418 def delete_queue_recording(self, **params):419 try:420 path = request.params.get("data")421 queue = request.params.get("queue_name")422 file_name = path.split("/")[len(path.split("/"))-1]423 dir = fs_vm_dir+session['context']+"/queue-recordings/"+queue+"/"424 os.remove(os.path.join(dir, file_name))425 except:426 return "Error..."427 return "Deleted queue recording."428 @authorize(logged_in)429 def get_queue_recordings(self):430 files = []431 queue = request.params.get("queue_name")432 dir = fs_vm_dir+session['context']+"/queue-recordings/"+queue433 for i in os.listdir(dir):434 path = dir+"/"+i435 id = i.split(".")[3].strip()436 row = PbxCdr.query.filter(PbxCdr.uuid==id).first()437 if row:438 caller = row.caller_id_number[len(row.caller_id_number)-10:]439 dest = row.destination_number440 agent = PbxCdr.query.filter(PbxCdr.uuid==row.bleg_uuid).first()441 agent_ext = agent.destination_number442 else:443 agent_ext = "No CDR"444 dest = "No CDR"445 caller = "No CDR"446 tpath = "/vm/" +session['context']+"/queue-recordings/"+queue+"/"+i447 received = str(modification_date(path)).strip("\"")448 fsize = str(os.path.getsize(path))449 files.append({'name': caller, 'queue': queue, 'destination': dest, 'agent': agent_ext, 'path': tpath, 'received': received, 'size': fsize})450 db.remove()451 out = dict({'identifier': 'path', 'label': 'name', 'items': files})452 response = make_response(out)453 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]454 return response(request.environ, self.start_response)455 @authorize(logged_in)456 def ad_audio(self):457 items = []458 dir = fs_vm_dir+session['context']+"/recordings/"459 try:460 for i in os.listdir(dir):461 fo = generateFileObject(i, "", dir)462 items.append({'id': '1,'+fo["name"], 'name': 'Recording: '+fo["name"] , 'data': fo["path"], 'type': 1, 'real_id': ""})463 db.remove()464 except:465 pass466 out = dict({'identifier': 'id', 'label': 'name', 'items': items})467 response = make_response(out)468 response.headers = [("Content-type", 'application/json; charset=UTF-8'),]469 return response(request.environ, self.start_response)470 ...

Full Screen

Full Screen

main.py

Source:main.py Github

copy

Full Screen

1import numpy as nm2import pytesseract3import re4import pydirectinput5import time6import cv27import math8from PIL import ImageGrab9from PIL import ImageFilter10import sched11import sys12import tkinter13from tkinter import ttk, simpledialog, messagebox14from throttle import *15import requests16import logging17from win32 import win32api18import webbrowser19import ctypes20from ahk import AHK21from multiprocessing import Process, Value22import socket23from flask import Flask24from flask import render_template25from flask import request, redirect, send_file26active = Value(ctypes.c_bool, False)27newchange = Value(ctypes.c_bool, False)28def ws(active, newchange):29 app = Flask(__name__)30 @app.route('/')31 def home():32 return render_template("index.html", toggle=active.value)33 @app.route('/status')34 def status():35 status = { "toggle": active.value }36 return status37 @app.route('/status/off')38 def status_off():39 active.value = False40 status = { "toggle": active.value, "response": 200 }41 return status42 @app.route('/status/on')43 def status_on():44 active.value = True45 status = { "toggle": active.value, "response": 200 }46 return status47 @app.route('/shot')48 def shot():49 im = ImageGrab.grab()50 im.save("temp/screenshot.png")51 return send_file("temp/screenshot.png", "PNG")52 @app.route("/send", methods=["POST"])53 def send():54 newchange.value = True55 form = request.form56 try:57 if form["switch"] == "on":58 active.value = True59 else:60 active.value = False61 except:62 active.value = False63 return redirect("/")64 def run():65 app.run(host='0.0.0.0', port='7878')66 run()67if __name__ == '__main__':68 root = tkinter.Tk()69 photo = tkinter.PhotoImage(file="img/ap_icon_new.png")70 root.title("button")71 screen_width = root.winfo_screenwidth()72 screen_height = root.winfo_screenheight()73 w = 5074 h = 5075 x = 10076 y = 10077 root.geometry('%dx%d+%d+%d' % (w, h, x, y))78 root.lift()79 root.overrideredirect(True)80 root.call('wm', 'attributes', '.', '-topmost', '1')81 button = tkinter.Button(root, text="button1",82 image=photo, bg="orange")83 button.grid(column=1, row=1, sticky=tkinter.E+tkinter.W)84 root.grid_columnconfigure(2, weight=2)85 try:86 ahk = AHK()87 except:88 print("AutoHotkey was not found! Please install it in order to continue.")89 exit()90 continue_route = False91 print("SCR-Autopilot v0.4.1-beta by MaTY")92 93 print("Checking for updates...")94 URL = "https://matyapi.matymt.repl.co/scr-autopilot/newest-version"95 r = requests.get(url=URL)96 data = r.json()97 version = data['version']98 if not version == "0.4.1":99 print("Your version is outdated! Please install the latest release on https://github.com/scr-autopilot/scr-autopilot/releases")100 outdatedask = messagebox.askyesno(101 "SCR-Autopilot", "Your version of SCR-Autopilot is outdated. Do you want to go to the releases page to download a new version?")102 if outdatedask == True:103 webbrowser.open(104 "https://github.com/scr-autopilot/scr-autopilot/releases")105 exit()106 else:107 print("Your version is up-to-date.")108 logging.basicConfig(filename='autopilot.log', filemode='w',109 level=logging.DEBUG, format="[%(levelname)s] [%(asctime)s] %(message)s")110 print("\nDisclaimer:\nSCR-Autopilot is still in a beta version so it can't handle some situations well.\nWe recommend using SCR-Autopilot on private servers.\nUSE OF THIS SOFTWARE AT YOUR RISK.\nWaiting for the user input in the dialog box.")111 warningask = messagebox.askokcancel("Disclaimer", "SCR-Autopilot is still in a beta version so it can't handle some situations well.\nWe recommend using SCR-Autopilot on private servers.\n\nUSE OF THIS SOFTWARE AT YOUR RISK.", icon='warning')112 if warningask == False:113 exit()114 display_size = ImageGrab.grab().size115 logging.debug(f'Display resolution: {display_size[0]}, {display_size[1]}')116 resolution = simpledialog.askstring(117 "Question", "What is the resolution? (fhd, hd)")118 if resolution == "fhd":119 spd_pos = 884, 957, 947, 985120 lim_pos = 889, 987, 942, 1016121 green_pos = 1440, 983, 1441, 984122 yellow_pos = 1438, 1016, 1439, 1017123 double_yellow_pos = 1438, 950, 1439, 951124 red_pos = 1438, 1045, 1439, 1046125 distance_pos = 555, 1046, 605, 1070126 awsbutton_pos = 1330, 994, 1331, 995127 throttle_pos = 843, 931, 845, 1074128 doors_pos = 870, 822, 871, 823129 loading_pos = 781, 823, 782, 824130 continue_pos = 1032, 460, 1033, 461131 undershoot_pos = 709, 906, 710, 907132 awaiting_pos = 862, 823, 863, 824133 buzzer_pos = 824, 816, 825, 817134 elif resolution == "hd":135 messagebox.showerror(136 "Error", 'HD resolution is not supported in this version of SCR-Autopilot. Please install v0.3.1-beta to use the HD resolution.')137 sys.exit()138 time.sleep(1)139 spd_pos = 573, 594, 630, 630140 lim_pos = 569, 627, 618, 653141 green_pos = 1118, 624, 1119, 625142 yellow_pos = 1120, 654, 1121, 655143 double_yellow_pos = 1120, 590, 1121, 591144 red_pos = 1120, 688, 1121, 689145 distance_pos = 239, 686, 284, 708146 awsbutton_pos = 1047, 597, 1048, 598147 throttle_pos = 522, 570, 525, 713148 else:149 messagebox.showerror(150 "Error", 'Please type only "fhd" (without the quotation marks) if you have FHD monitor, or type "hd" (without the quotation marks) if you have HD monitor.')151 sys.exit()152 max_speed = simpledialog.askinteger(153 "Question", "What is the maximum speed of your train in MPH? (E.g. 100, 125, 75 etc.)", minvalue=1)154 continue_ask = messagebox.askyesno(155 "Question", "Would you like to automatically continue in the route after finsihing?")156 if max_speed == None:157 messagebox.showerror("Error", 'Settings incorrect. Please try again.')158 exit()159 if continue_ask == True:160 continue_route = True161 PROCESS_PER_MONITOR_DPI_AWARE = 2162 MDT_EFFECTIVE_DPI = 0163 def print_dpi():164 shcore = ctypes.windll.shcore165 monitors = win32api.EnumDisplayMonitors()166 hresult = shcore.SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE)167 assert hresult == 0168 dpiX = ctypes.c_uint()169 dpiY = ctypes.c_uint()170 for i, monitor in enumerate(monitors):171 shcore.GetDpiForMonitor(172 monitor[0].handle,173 MDT_EFFECTIVE_DPI,174 ctypes.byref(dpiX),175 ctypes.byref(dpiY)176 )177 logging.debug(178 f"Monitor {i} = dpiX: {dpiX.value}, dpiY: {dpiY.value}"179 )180 print_dpi()181 pytesseract.pytesseract.tesseract_cmd = 'C:/Program Files (x86)/Tesseract-OCR/tesseract.exe'182 time.sleep(1)183 solve = None184 continuing = False185 ignorelim = False186 ignoreaws = False187 wsask = continue_ask = messagebox.askyesno(188 "Question", "Would you like to start a webserver so you can remotely control the autopilot?")189 if wsask == True:190 print("Starting the webserver...")191 p = Process(target=ws, args=(active,newchange,))192 p.start()193 time.sleep(3)194 print("\n\n\n\n\n\n\n\n\n\n\n\n\n\n")195 print(""" ___ ___ ___ _ _ _ _ _ 196 / __|/ __| _ \___ /_\ _ _| |_ ___ _ __(_) |___| |_197 \__ \ (__| /___/ _ \ || | _/ _ \ '_ \ | / _ \ _|198 |___/\___|_|_\ /_/ \_\_,_|\__\___/ .__/_|_\___/\__|199 |_| 200 """)201 print("Press the red button that has appeared on your screen to engage the autopilot. You can press the button again to disengage the autopilot.")202 if wsask == True:203 print("\n\nFor the remote control, navigate to:", "http://" + socket.gethostbyname(socket.gethostname()) + ":7878 on a different device.","\nYou need to be on a same network to open the website.\n\n")204 print("Settings:")205 print("Screen resolution:", resolution)206 print("Train max speed:", max_speed)207 print("Automatically continue:", continue_route)208 def task():209 global solve210 global continuing211 global ignorelim212 global ignoreaws213 print("ignorelim", ignorelim)214 if continue_route == True:215 im = ImageGrab.grab(bbox=(continue_pos))216 pix = im.load()217 continue_value = pix[0, 0] # Set the RGBA Value of the image (tuple)218 if continue_value == (255, 255, 255):219 continuing = True220 ahk.click(991, 470)221 ahk.click(327, 833)222 im = ImageGrab.grab(bbox=(awsbutton_pos))223 pix = im.load()224 awsbutton_value = pix[0, 0] # Set the RGBA Value of the image (tuple)225 if awsbutton_value == (255, 255, 255):226 pydirectinput.keyDown("q")227 pydirectinput.keyUp("q")228 print("Reset the AWS")229 logging.debug(f'AWS pixel RGB: {awsbutton_value}')230 cap = ImageGrab.grab(bbox=(throttle_pos))231 img = cap232 count = 0233 bottom_throttle_pixel = None234 for y in range(img.height):235 for x in range(img.width):236 pixel = img.getpixel((x, y))237 if y == img.height - 1:238 bottom_throttle_pixel = pixel239 if pixel == (0, 176, 85):240 count += 1241 currentThrottle = int(math.floor(100 * (count / 142)))242 speed = currentThrottle/100 * max_speed243 if currentThrottle == 0:244 logging.debug(f'Throttle pixel RGB: {bottom_throttle_pixel}')245 print("Current throttle: ", currentThrottle)246 if currentThrottle == None:247 messagebox.showerror("Error", "I can't read the throttle")248 supportask = messagebox.askyesno(249 "Question", "It looks like you got an error. You can try again, but if this error persists, you can join the support server. Do you want to join the support server on Discord?")250 if supportask == True:251 webbrowser.open(252 "https://discord.gg/jtQ2R8cxWq")253 exit()254 else:255 # LIMIT256 cap = ImageGrab.grab(bbox=(lim_pos))257 cap = cap.filter(ImageFilter.MedianFilter())258 cap = cv2.cvtColor(nm.array(cap), cv2.COLOR_RGB2GRAY)259 tesstr = pytesseract.image_to_string(260 cap,261 config="--psm 7")262 lim = 0263 lim = [int(s) for s in re.findall(r'\b\d+\b', tesstr)]264 if lim == []:265 if continuing == False and ignorelim == False:266 messagebox.showerror("Error", "I can't read the limit")267 supportask = messagebox.askyesno(268 "Question", "It looks like you got an error. You can try again, but if this error persists, you can join the support server. Do you want to join the support server on Discord?")269 if supportask == True:270 webbrowser.open(271 "https://discord.gg/jtQ2R8cxWq")272 exit()273 else:274 cap = ImageGrab.grab()275 src = nm.array(cap)276 gray = cv2.cvtColor(src, cv2.COLOR_RGB2GRAY)277 gray = cv2.medianBlur(gray, 5)278 rows = gray.shape[0]279 circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, rows / 8,280 param1=100, param2=30,281 minRadius=1, maxRadius=30)282 283 if circles is not None:284 circles = nm.uint16(nm.around(circles))285 for i in circles[0, :]:286 x = i[0] - i[2]287 y = i[1] - i[2]288 w = 2*i[2]289 h = 2*i[2]290 center = (i[0], i[1])291 if w > 39:292 txt = pytesseract.image_to_string(gray[y:y+h, x:x+w], config="--psm 6")293 if "W" in txt:294 pydirectinput.keyDown("h")295 pydirectinput.keyUp("h")296 cv2.circle(src, center, 1, (0, 100, 100), 3)297 radius = i[2]298 cv2.circle(src, center, radius, (255, 0, 255), 3)299 templim = lim[0]300 lim = lim[0]301 lim = int(lim)302 if ignoreaws == False:303 im = ImageGrab.grab(bbox=(red_pos))304 pix = im.load()305 # Set the RGBA Value of the image (tuple)306 red_value = pix[0, 0]307 im = ImageGrab.grab(bbox=(yellow_pos))308 pix = im.load()309 # Set the RGBA Value of the image (tuple)310 yellow_value = pix[0, 0]311 im = ImageGrab.grab(bbox=(green_pos))312 pix = im.load()313 # Set the RGBA Value of the image (tuple)314 green_value = pix[0, 0]315 im = ImageGrab.grab(bbox=(double_yellow_pos))316 pix = im.load()317 # Set the RGBA Value of the image (tuple)318 double_yellow_value = pix[0, 0]319 if red_value == (255, 0, 0):320 print("AWS:", "red")321 lim = 0322 if yellow_value == (255, 190, 0):323 print("AWS:", "yellow")324 if templim > 45:325 lim = 45326 if double_yellow_value == (255, 190, 0):327 print("AWS:", "double_yellow")328 if templim > 75:329 lim = 75330 if green_value == (0, 255, 0):331 print("AWS:", "green")332 print("Limit: ", lim)333 limitThrottle = int((lim / max_speed) * 100)334 print("Limit throttle: ", limitThrottle)335 cap = ImageGrab.grab(bbox=(distance_pos))336 cap = cap.filter(ImageFilter.MedianFilter())337 cap = cv2.cvtColor(nm.array(cap), cv2.COLOR_RGB2GRAY)338 tesstr = pytesseract.image_to_string(339 cap,340 config="--psm 6")341 distance = 0342 distance = [int(s) for s in re.findall(r'\b\d+\b', tesstr)]343 try:344 m_distance = distance[0]345 distance = distance[1]346 print(m_distance, distance)347 if distance == 00 and m_distance == 0 or continuing == True:348 im = ImageGrab.grab(bbox=(loading_pos))349 pix = im.load()350 loading_value = pix[0, 0]351 im = ImageGrab.grab(bbox=(doors_pos))352 pix = im.load()353 doors_value = pix[0, 0]354 im = ImageGrab.grab(bbox=(undershoot_pos))355 pix = im.load()356 undershoot_value = pix[0, 0]357 im = ImageGrab.grab(bbox=(awaiting_pos))358 pix = im.load()359 awaiting_value = pix[0, 0]360 im = ImageGrab.grab(bbox=(buzzer_pos))361 pix = im.load()362 buzzer_value = pix[0, 0]363 print(buzzer_value)364 if undershoot_value == (255, 255, 255):365 print("UNDERSHOOT")366 pydirectinput.keyDown("w")367 time.sleep(0.4)368 pydirectinput.keyUp("w")369 if doors_value == (255, 255, 255):370 print("CLOSING DOORS")371 pydirectinput.keyDown("t")372 pydirectinput.keyUp("t")373 time.sleep(4)374 continuing = False375 ignorelim = False376 ignoreaws = False377 elif loading_value == (255, 255, 255):378 print("LOADING")379 elif awaiting_value == (255, 255, 255):380 print("WAITING FOR GUARD")381 elif buzzer_value == (255, 255, 255):382 print("ACTIVATING THE BUZZER")383 pydirectinput.keyDown("t")384 pydirectinput.keyUp("t")385 else:386 print("Autopilot is currently stopping.")387 pydirectinput.keyDown("s")388 time.sleep(5)389 pydirectinput.keyUp("s")390 pydirectinput.keyDown("t")391 pydirectinput.keyUp("t")392 elif distance <= 20 and m_distance == 0:393 if lim >= 45:394 print("Slowing down to prepare for station arrival.")395 ignoreaws = True396 ignorelim = True397 throttle(currentThrottle, int((42 / max_speed) * 100))398 else:399 throttle(currentThrottle, limitThrottle)400 else:401 throttle(currentThrottle, limitThrottle)402 except IndexError:403 pass404 solve = root.after(600, task)405 checkChanges = None406 def f_checkChanges():407 global checkChanges408 if newchange.value == True:409 newchange.value = False410 if active.value == True:411 button.configure(bg="green")412 root.after(600, task)413 elif active.value == False:414 button.configure(bg="red")415 try:416 root.after_cancel(solve)417 except:418 print("Error...")419 checkChanges = root.after(2000, f_checkChanges)420 checkChanges = root.after(2000, f_checkChanges)421 def onClick():422 if active.value == False:423 active.value = True424 button.configure(bg="green")425 root.after(600, task)426 else:427 active.value = False428 button.configure(bg="red")429 root.after_cancel(solve)430 button.configure(bg="red", command=onClick)431 switchask = messagebox.askyesno(432 "SCR-Autopilot", 'Autopilot is set up. Do you want to turn it on now? You can also turn it on or off by using the "AP" button on your screen.')433 if switchask == True:434 onClick()...

Full Screen

Full Screen

_network.py

Source:_network.py Github

copy

Full Screen

...234 await self._race_with_page_close(235 self._channel.send("continue", cast(Any, overrides))236 )237 def _internal_continue(self) -> None:238 async def continue_route() -> None:239 try:240 await self.continue_()241 except Exception:242 pass243 asyncio.create_task(continue_route())244 async def _race_with_page_close(self, future: Coroutine) -> None:245 if hasattr(self.request.frame, "_page"):246 page = self.request.frame._page247 # When page closes or crashes, we catch any potential rejects from this Route.248 # Note that page could be missing when routing popup's initial request that249 # does not have a Page initialized just yet.250 fut = asyncio.create_task(future)251 await asyncio.wait(252 [fut, page._closed_or_crashed_future],253 return_when=asyncio.FIRST_COMPLETED,254 )255 if page._closed_or_crashed_future.done():256 await asyncio.gather(fut, return_exceptions=True)257 else:...

Full Screen

Full Screen

Playwright tutorial

LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.

Chapters:

  1. What is Playwright : Playwright is comparatively new but has gained good popularity. Get to know some history of the Playwright with some interesting facts connected with it.
  2. How To Install Playwright : Learn in detail about what basic configuration and dependencies are required for installing Playwright and run a test. Get a step-by-step direction for installing the Playwright automation framework.
  3. Playwright Futuristic Features: Launched in 2020, Playwright gained huge popularity quickly because of some obliging features such as Playwright Test Generator and Inspector, Playwright Reporter, Playwright auto-waiting mechanism and etc. Read up on those features to master Playwright testing.
  4. What is Component Testing: Component testing in Playwright is a unique feature that allows a tester to test a single component of a web application without integrating them with other elements. Learn how to perform Component testing on the Playwright automation framework.
  5. Inputs And Buttons In Playwright: Every website has Input boxes and buttons; learn about testing inputs and buttons with different scenarios and examples.
  6. Functions and Selectors in Playwright: Learn how to launch the Chromium browser with Playwright. Also, gain a better understanding of some important functions like “BrowserContext,” which allows you to run multiple browser sessions, and “newPage” which interacts with a page.
  7. Handling Alerts and Dropdowns in Playwright : Playwright interact with different types of alerts and pop-ups, such as simple, confirmation, and prompt, and different types of dropdowns, such as single selector and multi-selector get your hands-on with handling alerts and dropdown in Playright testing.
  8. Playwright vs Puppeteer: Get to know about the difference between two testing frameworks and how they are different than one another, which browsers they support, and what features they provide.
  9. Run Playwright Tests on LambdaTest: Playwright testing with LambdaTest leverages test performance to the utmost. You can run multiple Playwright tests in Parallel with the LammbdaTest test cloud. Get a step-by-step guide to run your Playwright test on the LambdaTest platform.
  10. Playwright Python Tutorial: Playwright automation framework support all major languages such as Python, JavaScript, TypeScript, .NET and etc. However, there are various advantages to Python end-to-end testing with Playwright because of its versatile utility. Get the hang of Playwright python testing with this chapter.
  11. Playwright End To End Testing Tutorial: Get your hands on with Playwright end-to-end testing and learn to use some exciting features such as TraceViewer, Debugging, Networking, Component testing, Visual testing, and many more.
  12. Playwright Video Tutorial: Watch the video tutorials on Playwright testing from experts and get a consecutive in-depth explanation of Playwright automation testing.

Run Playwright Python automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful