SHOW:
|
|
- or go back to the newest paste.
1 | #! /usr/bin/python | |
2 | # -*- encoding: utf-8 -*- | |
3 | ||
4 | import xmlrpclib | |
5 | import sys | |
6 | from optparse import OptionParser | |
7 | ||
8 | ||
9 | # CID Name that will be displayed if there is no match in res.partner.address | |
10 | default_cid_name = "Not in OpenERP" | |
11 | ||
12 | # Define command line options | |
13 | option_server = {'names': ('-s', '--server'), 'dest': 'server', 'type': 'string', 'help': 'DNS or IP address of the OpenERP server. Default = localhost', 'action': 'store', 'default':'localhost'} | |
14 | option_port = {'names': ('-p', '--port'), 'dest': 'port', 'type': 'int', 'help': "Port of OpenERP's XML-RPC interface. Default = 8069", 'action': 'store', 'default': 8069} | |
15 | option_database = {'names': ('-d', '--database'), 'dest': 'database', 'type': 'string', 'help': "OpenERP database name. Default = openerp", 'action': 'store', 'default': 'openerp'} | |
16 | option_user = {'names': ('-u', '--user-id'), 'dest': 'user', 'type': 'int', 'help': "OpenERP user ID to use when connecting to OpenERP. Default = 2", 'action': 'store', 'default': 2} | |
17 | option_password = {'names': ('-w', '--password'), 'dest': 'password', 'type': 'string', 'help': "Password of the OpenERP user. Default = demo", 'action': 'store', 'default': 'demo'} | |
18 | option_ascii = {'names': ('-a', '--ascii'), 'dest': 'ascii', 'help': "Convert name from UTF-8 to ASCII. Default = no, keep UTF-8", 'action': 'store_true', 'default': False} | |
19 | ||
20 | options = [option_server, option_port, option_database, option_user, option_password, option_ascii] | |
21 | ||
22 | def stdout_write(string): | |
23 | '''Wrapper on sys.stdout.write''' | |
24 | sys.stdout.write(string.encode(sys.stdout.encoding, 'replace')) | |
25 | sys.stdout.flush() | |
26 | ||
27 | def stderr_write(string): | |
28 | '''Wrapper on sys.stderr.write''' | |
29 | sys.stderr.write(string.encode(sys.stdout.encoding, 'replace')) | |
30 | sys.stdout.flush() | |
31 | ||
32 | ||
33 | def reformat_phone_number_before_query_openerp(number): | |
34 | '''We match only on the end of the phone number''' | |
35 | if len(number) >= 9: | |
36 | return number[-9:len(number)] # Take 9 last numbers | |
37 | else: | |
38 | return number | |
39 | ||
40 | def convert_to_ascii(my_unicode): | |
41 | '''Convert to ascii, with clever management of accents (é -> e, è -> e)''' | |
42 | import unicodedata | |
43 | if isinstance(my_unicode, unicode): | |
44 | my_unicode_with_ascii_chars_only = ''.join((char for char in unicodedata.normalize('NFD', my_unicode) if unicodedata.category(char) != 'Mn')) | |
45 | return str(my_unicode_with_ascii_chars_only) | |
46 | # If the argument is already of string type, we return it with the same value | |
47 | elif isinstance(my_unicode, str): | |
48 | return my_unicode | |
49 | else: | |
50 | return False | |
51 | ||
52 | def main(options, arguments): | |
53 | #print 'options = %s' % options | |
54 | #print 'arguments = %s' % arguments | |
55 | ||
56 | # AGI passes parameters to the script on standard input | |
57 | stdinput = {} | |
58 | while 1: | |
59 | input_line = sys.stdin.readline().strip() | |
60 | if input_line == '': | |
61 | break | |
62 | variable, value = input_line.split(':') # TODO à protéger ! | |
63 | if variable[:4] != 'agi_': # All AGI parameters start with 'agi_' | |
64 | stderr_write("bad stdin variable : %s\n" % variable) | |
65 | continue | |
66 | variable = variable.strip() | |
67 | value = value.strip() | |
68 | if variable != '': | |
69 | stdinput[variable] = value | |
70 | stderr_write("full AGI environnement :\n") | |
71 | for variable in stdinput.keys(): | |
72 | stderr_write("%s = %s\n" % (variable, stdinput[variable])) | |
73 | ||
74 | input_cid_number = stdinput.get('agi_callerid', False) | |
75 | stderr_write('stdout encoding = %s\n' % sys.stdout.encoding) | |
76 | ||
77 | if not isinstance(input_cid_number, str): | |
78 | exit(0) | |
79 | # Match for particular cases and anonymous phone calls | |
80 | # To test anonymous call in France, dial 3651 + number | |
81 | if not input_cid_number.isdigit(): | |
82 | stdout_write('VERBOSE "CallerID number (%s) is not a digit"\n' % input_cid_number) | |
83 | exit(0) | |
84 | ||
85 | stdout_write('VERBOSE "CallerID number = %s"\n' % input_cid_number) | |
86 | query_number = reformat_phone_number_before_query_openerp(input_cid_number) | |
87 | stderr_write("phone number sent to OpenERP = %s\n" % query_number) | |
88 | ||
89 | stdout_write('VERBOSE "Starting XML-RPC request on OpenERP %s:%s"\n' % (options.server, str(options.port))) | |
90 | ||
91 | sock = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/object' % (options.server, str(options.port))) | |
92 | ||
93 | res = sock.execute(options.database, options.user, options.password, 'res.partner.address', 'get_name_from_phone_number', query_number) | |
94 | # To simulate a long execution of the XML-RPC request | |
95 | #import time | |
96 | #time.sleep(5) | |
97 | ||
98 | stdout_write('VERBOSE "End of XML-RPC request on OpenERP"\n') | |
99 | ||
100 | # Function to limit the size of the CID name to 40 chars | |
101 | if res: | |
102 | if len(res) > 40: | |
103 | res = res[0:40] | |
104 | else: | |
105 | # if the number is not found in OpenERP, we put 'default_cid_name' as CID Name | |
106 | res = default_cid_name | |
107 | ||
108 | # All SIP phones should support UTF-8... but in case you have analog phones over TDM | |
109 | # or buggy phones, you should use the command line option --ascii | |
110 | if options.ascii: | |
111 | res = convert_to_ascii(res) | |
112 | ||
113 | stdout_write('VERBOSE "CallerID Name = %s"\n' % res) | |
114 | stdout_write('SET CALLERID "%s"<%s>\n' % (res, input_cid_number)) | |
115 | ||
116 | if __name__ == '__main__': | |
117 | - | parser = OptionParser() |
117 | + | |
118 | - | for option in options: |
118 | + | |
119 | - | param = option['names'] |
119 | + | |
120 | - | del option['names'] |
120 | + | |
121 | - | parser.add_option(*param, **option) |
121 | + | |
122 | - | options, arguments = parser.parse_args() |
122 | + | |
123 | - | sys.argv[:] = arguments |
123 | + | |
124 | - | main(options, arguments) |
124 | + | |
125 | # CID Name that will be displayed if there is no match in res.partner.address | |
126 | default_cid_name = "Not in OpenERP" | |
127 | ||
128 | # Define command line options | |
129 | option_server = {'names': ('-s', '--server'), 'dest': 'server', 'type': 'string', 'help': 'DNS or IP address of the OpenERP server. Default = localhost', 'action': 'store', 'default':'localhost'} | |
130 | option_port = {'names': ('-p', '--port'), 'dest': 'port', 'type': 'int', 'help': "Port of OpenERP's XML-RPC interface. Default = 8069", 'action': 'store', 'default': 8069} | |
131 | option_database = {'names': ('-d', '--database'), 'dest': 'database', 'type': 'string', 'help': "OpenERP database name. Default = openerp", 'action': 'store', 'default': 'openerp'} | |
132 | option_user = {'names': ('-u', '--user-id'), 'dest': 'user', 'type': 'int', 'help': "OpenERP user ID to use when connecting to OpenERP. Default = 2", 'action': 'store', 'default': 2} | |
133 | option_password = {'names': ('-w', '--password'), 'dest': 'password', 'type': 'string', 'help': "Password of the OpenERP user. Default = demo", 'action': 'store', 'default': 'demo'} | |
134 | option_ascii = {'names': ('-a', '--ascii'), 'dest': 'ascii', 'help': "Convert name from UTF-8 to ASCII. Default = no, keep UTF-8", 'action': 'store_true', 'default': False} | |
135 | ||
136 | options = [option_server, option_port, option_database, option_user, option_password, option_ascii] | |
137 | ||
138 | def stdout_write(string): | |
139 | '''Wrapper on sys.stdout.write''' | |
140 | sys.stdout.write(string.encode(sys.stdout.encoding, 'replace')) | |
141 | sys.stdout.flush() | |
142 | ||
143 | def stderr_write(string): | |
144 | '''Wrapper on sys.stderr.write''' | |
145 | sys.stderr.write(string.encode(sys.stdout.encoding, 'replace')) | |
146 | sys.stdout.flush() | |
147 | ||
148 | ||
149 | def reformat_phone_number_before_query_openerp(number): | |
150 | '''We match only on the end of the phone number''' | |
151 | if len(number) >= 9: | |
152 | return number[-9:len(number)] # Take 9 last numbers | |
153 | else: | |
154 | return number | |
155 | ||
156 | def convert_to_ascii(my_unicode): | |
157 | '''Convert to ascii, with clever management of accents (é -> e, è -> e)''' | |
158 | import unicodedata | |
159 | if isinstance(my_unicode, unicode): | |
160 | my_unicode_with_ascii_chars_only = ''.join((char for char in unicodedata.normalize('NFD', my_unicode) if unicodedata.category(char) != 'Mn')) | |
161 | return str(my_unicode_with_ascii_chars_only) | |
162 | # If the argument is already of string type, we return it with the same value | |
163 | elif isinstance(my_unicode, str): | |
164 | return my_unicode | |
165 | else: | |
166 | return False | |
167 | ||
168 | def main(options, arguments): | |
169 | #print 'options = %s' % options | |
170 | #print 'arguments = %s' % arguments | |
171 | ||
172 | # AGI passes parameters to the script on standard input | |
173 | stdinput = {} | |
174 | while 1: | |
175 | input_line = sys.stdin.readline().strip() | |
176 | if input_line == '': | |
177 | break | |
178 | variable, value = input_line.split(':') # TODO à protéger ! | |
179 | if variable[:4] != 'agi_': # All AGI parameters start with 'agi_' | |
180 | stderr_write("bad stdin variable : %s\n" % variable) | |
181 | continue | |
182 | variable = variable.strip() | |
183 | value = value.strip() | |
184 | if variable != '': | |
185 | stdinput[variable] = value | |
186 | stderr_write("full AGI environnement :\n") | |
187 | for variable in stdinput.keys(): | |
188 | stderr_write("%s = %s\n" % (variable, stdinput[variable])) | |
189 | ||
190 | input_cid_number = stdinput.get('agi_callerid', False) | |
191 | stderr_write('stdout encoding = %s\n' % sys.stdout.encoding) | |
192 | ||
193 | if not isinstance(input_cid_number, str): | |
194 | exit(0) | |
195 | # Match for particular cases and anonymous phone calls | |
196 | # To test anonymous call in France, dial 3651 + number | |
197 | if not input_cid_number.isdigit(): | |
198 | stdout_write('VERBOSE "CallerID number (%s) is not a digit"\n' % input_cid_number) | |
199 | exit(0) | |
200 | ||
201 | stdout_write('VERBOSE "CallerID number = %s"\n' % input_cid_number) | |
202 | query_number = reformat_phone_number_before_query_openerp(input_cid_number) | |
203 | stderr_write("phone number sent to OpenERP = %s\n" % query_number) | |
204 | ||
205 | stdout_write('VERBOSE "Starting XML-RPC request on OpenERP %s:%s"\n' % (options.server, str(options.port))) | |
206 | ||
207 | sock = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/object' % (options.server, str(options.port))) | |
208 | ||
209 | res = sock.execute(options.database, options.user, options.password, 'res.partner.address', 'get_name_from_phone_number', query_number) | |
210 | # To simulate a long execution of the XML-RPC request | |
211 | #import time | |
212 | #time.sleep(5) | |
213 | ||
214 | stdout_write('VERBOSE "End of XML-RPC request on OpenERP"\n') | |
215 | ||
216 | # Function to limit the size of the CID name to 40 chars | |
217 | if res: | |
218 | if len(res) > 40: | |
219 | res = res[0:40] | |
220 | else: | |
221 | # if the number is not found in OpenERP, we put 'default_cid_name' as CID Name | |
222 | res = default_cid_name | |
223 | ||
224 | # All SIP phones should support UTF-8... but in case you have analog phones over TDM | |
225 | # or buggy phones, you should use the command line option --ascii | |
226 | if options.ascii: | |
227 | res = convert_to_ascii(res) | |
228 | ||
229 | stdout_write('VERBOSE "CallerID Name = %s"\n' % res) | |
230 | stdout_write('SET CALLERID "%s"<%s>\n' % (res, input_cid_number)) | |
231 | ||
232 | if __name__ == '__main__': | |
233 | try: | |
234 | parser = OptionParser() | |
235 | for option in options: | |
236 | param = option['names'] | |
237 | del option['names'] | |
238 | parser.add_option(*param, **option) | |
239 | options, arguments = parser.parse_args() | |
240 | sys.argv[:] = arguments | |
241 | main(options, arguments) | |
242 | except Exception as e: | |
243 | f = open('/tmp/my-custom-log', 'w') | |
244 | f.write('ERROR: %s\n' %str(e)) | |
245 | f.close() |