11from dataclasses import asdict , dataclass
22
3- import asyncio
43import chevron
54import json
65import logging
2019from phonenumbers .geocoder import country_name_for_number , description_for_number
2120from typing import Optional
2221
23- from src .ext import ApiError , MessageBird
22+ from src .ext import MessageBird
2423from src .render .main import MessageTooLong , SmsLength , apply_short_links , sms_length
2524from src .schemas .messages import MessageStatus , SmsRecipientModel , SmsSendMethod , SmsSendModel
2625from src .settings import Settings
@@ -127,7 +126,6 @@ async def _test_send_sms(self, sms_data: SmsData):
127126 # remove the + from the beginning of the number
128127 msg_id = f'{ self .m .uid } -{ sms_data .number .number [1 :]} '
129128 send_ts = utcnow ()
130- cost = 0.012 * sms_data .length .parts
131129 output = (
132130 f'to: { sms_data .number } \n '
133131 f'msg id: { msg_id } \n '
@@ -136,7 +134,6 @@ async def _test_send_sms(self, sms_data: SmsData):
136134 f'tags: { self .tags } \n '
137135 f'company_code: { self .m .company_code } \n '
138136 f'from_name: { self .from_name } \n '
139- f'cost: { cost } \n '
140137 f'length: { sms_data .length } \n '
141138 f'message:\n '
142139 f'{ sms_data .message } \n '
@@ -146,85 +143,12 @@ async def _test_send_sms(self, sms_data: SmsData):
146143 save_path = self .settings .test_output / f'{ msg_id } .txt'
147144 test_logger .info ('sending message: %s (saved to %s)' , output , save_path )
148145 save_path .write_text (output )
149- await self ._store_sms (msg_id , send_ts , sms_data , cost )
150-
151- async def _messagebird_get_mcc_cost (self , redis , mcc ):
152- rates_key = 'messagebird-rates'
153- if not await redis .exists (rates_key ):
154- # get fresh data on rates by mcc
155- main_logger .info ('getting fresh pricing data from messagebird...' )
156- r = await self .messagebird .get ('pricing/sms/outbound' )
157- if r .status_code != 200 :
158- response = r .text
159- main_logger .error (
160- 'error getting messagebird api' , extra = {'status' : r .status_code , 'response' : response }
161- )
162- raise MessageBirdExternalError ((r .status_code , response ))
163- data = r .json ()
164- prices = data ['prices' ]
165- if not next ((1 for g in prices if g ['mcc' ] == '0' ), None ):
166- main_logger .error ('no default messagebird pricing with mcc "0"' , extra = {'prices' : prices })
167- prices = {g ['mcc' ]: f'{ float (g ["price" ]):0.5f} ' for g in prices }
168- await asyncio .gather (redis .hmset_dict (rates_key , prices ), redis .expire (rates_key , ONE_DAY ))
169- rate = await redis .hget (rates_key , mcc , encoding = 'utf8' )
170- if not rate :
171- main_logger .warning ('no rate found for mcc: "%s", using default' , mcc )
172- rate = await redis .hget (rates_key , '0' , encoding = 'utf8' )
173- assert rate , f'no rate found for mcc: { mcc } '
174- return float (rate )
175-
176- async def _messagebird_get_number_cost (self , number : Number ):
177- cc_mcc_key = f'messagebird-cc:{ number .country_code } '
178- with await self .ctx ['redis' ] as redis :
179- mcc = await redis .get (cc_mcc_key )
180- if mcc is None :
181- main_logger .info ('no mcc for %s, doing HLR lookup...' , number .number )
182- api_number = number .number .replace ('+' , '' )
183-
184- data = {'msisdn' : api_number }
185- response = await self .messagebird .post ('hlr' , ** data )
186- hlr_data = response .json ()
187- hlr_id = hlr_data .get ('id' )
188-
189- network , hlr = None , None
190- for i in range (60 ):
191- try :
192- r = await self .messagebird .get (f'hlr/{ hlr_id } ' )
193- except ApiError :
194- main_logger .info ('Error retrieving HLR data for %s, attempt %d' , number .number , i )
195- continue
196- hlr = r .json ()
197- if hlr .get ('errors' ):
198- continue
199- network = hlr .get ('network' )
200- if not network :
201- continue
202- elif hlr ['status' ] == 'active' :
203- main_logger .info (
204- 'found result for %s after %d attempts %s' , number .number , i , json .dumps (hlr , indent = 2 )
205- )
206- break
207- await asyncio .sleep (1 )
208- if not hlr or not network :
209- main_logger .warning ('No HLR result found for %s after 30 attempts' , number .number , extra = hlr )
210- return
211- mcc = str (network )[:3 ]
212- await redis .setex (cc_mcc_key , ONE_YEAR , mcc )
213- return await self ._messagebird_get_mcc_cost (redis , mcc )
146+ await self ._store_sms (msg_id , send_ts , sms_data )
214147
215148 async def _messagebird_send_sms (self , sms_data : SmsData ):
216- try :
217- msg_cost = await self ._messagebird_get_number_cost (sms_data .number )
218- except MessageBirdExternalError :
219- msg_cost = 0 # Set to SMS cost to 0 until cost API is working/changed
220- if msg_cost is None :
221- return
222-
223- cost = sms_data .length .parts * msg_cost
224149 send_ts = utcnow ()
225- main_logger .info (
226- 'sending SMS to %s, parts: %d, cost: %0.2fp' , sms_data .number .number , sms_data .length .parts , cost * 100
227- )
150+ main_logger .info ('sending SMS to %s, parts: %d' , sms_data .number .number , sms_data .length .parts )
151+
228152 r = await self .messagebird .post (
229153 'messages' ,
230154 originator = self .from_name ,
@@ -237,9 +161,9 @@ async def _messagebird_send_sms(self, sms_data: SmsData):
237161 data = r .json ()
238162 if data ['recipients' ]['totalCount' ] != 1 :
239163 main_logger .error ('not one recipients in send response' , extra = {'data' : data })
240- await self ._store_sms (data ['id' ], send_ts , sms_data , cost )
164+ await self ._store_sms (data ['id' ], send_ts , sms_data )
241165
242- async def _store_sms (self , external_id , send_ts , sms_data : SmsData , cost : float ):
166+ async def _store_sms (self , external_id , send_ts , sms_data : SmsData ):
243167 message_id = await glove .pg .fetchval_b (
244168 'insert into messages (:values__names) values :values returning id' ,
245169 values = Values (
@@ -255,7 +179,6 @@ async def _store_sms(self, external_id, send_ts, sms_data: SmsData, cost: float)
255179 to_address = sms_data .number .number_formatted ,
256180 tags = self .tags ,
257181 body = sms_data .message ,
258- cost = cost ,
259182 extra = json .dumps (asdict (sms_data .length )),
260183 ),
261184 )
0 commit comments