Skip to content

Instantly share code, notes, and snippets.

@bkbilly
Last active April 3, 2025 18:18
Show Gist options
  • Select an option

  • Save bkbilly/3f824ee42e72b95ce9addcbc1f81f3e0 to your computer and use it in GitHub Desktop.

Select an option

Save bkbilly/3f824ee42e72b95ce9addcbc1f81f3e0 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
''' This application returns the the remaining minutes in the asterisk format
ex: the 326 minutes are returned as 300 20 6'''
import csv
import re
import datetime
import logging
import sys
import click
logging.basicConfig(
format='%(asctime)s - %(levelname)s - %(message)s',
level=logging.WARNING
)
class AsteriskShowLimit():
def __init__(self, sipFilter='vodafone', freeTime=18000, startDay=1, extraTime=15, cliMatch="69[0-9]+"):
self.totalFreeTime = freeTime # Free seconds given by provider
self.startDay = startDay # The Month Day that starts counting from
self.extraTime = extraTime # Extra time to compensate the lack of answer detection
self.cliMatch = cliMatch # Filters only for mobiles
self.sipFilter = sipFilter # Filters the sip that is calling
self.countDuration = self.getCurrentDuration()
self.remainingTime = self.getRemainingTime()
asteriskPrint = self.getAsteriskPrint()
print(asteriskPrint)
def getStartDateTime(self):
# Current Date
nowDay = datetime.datetime.now().day
nowMonth = datetime.datetime.now().month
nowYear = datetime.datetime.now().year
if nowMonth != 1:
if datetime.datetime(nowYear, nowMonth, self.startDay) <= datetime.datetime.now():
startDatetime = datetime.datetime(nowYear, nowMonth, self.startDay)
elif datetime.datetime(nowYear, nowMonth-1, self.startDay) <= datetime.datetime.now():
startDatetime = datetime.datetime(nowYear, nowMonth-1, self.startDay)
else:
if datetime.datetime(nowYear, nowMonth, self.startDay) <= datetime.datetime.now():
startDatetime = datetime.datetime(nowYear, nowMonth, self.startDay)
elif datetime.datetime(nowYear-1, 12, self.startDay) <= datetime.datetime.now():
startDatetime = datetime.datetime(nowYear-1, 12, self.startDay)
return startDatetime
def getCurrentDuration(self):
# Read the csv log of asterisk into a list of lists
with open('/var/log/asterisk/cdr-csv/Master.csv', 'r') as f:
reader = csv.reader(f)
asteriskLog = list(reader)
asteriskLog.reverse() # Read log botton up
countDuration = 0
for callLog in asteriskLog:
log_from = callLog[1]
log_to = callLog[2]
dialplan = callLog[3]
log_duration = int(callLog[13])
sip = re.findall(r".*\/(.*)-.*", callLog[6])
if len(sip) == 1:
sip = sip[0]
# Calculate the duration
if log_duration > self.extraTime:
log_duration -= self.extraTime
log_date = datetime.datetime.strptime(callLog[9], '%Y-%m-%d %H:%M:%S')
# Read until the specified date
if log_date < self.getStartDateTime():
break
# Calculate on specified phone number
if sip == self.sipFilter and log_duration > 0 and re.match(self.cliMatch, log_to):
logging.info(callLog)
logging.info('dialplan: %s' % (dialplan))
logging.info('sip: %s' % (sip))
logging.info('countDuration: %s' % (countDuration))
if (log_duration % 60) == 0:
logging.info('log_duration: %s' % (log_duration))
countDuration += log_duration
else:
logging.info('log_duration: %s' % (log_duration - (log_duration % 60) + 60))
countDuration += log_duration - (log_duration % 60) + 60
return countDuration
def getRemainingTime(self):
# Charge per minute
remainingTime = (self.totalFreeTime - self.countDuration)/60
if remainingTime < 0:
remainingTime = 0
return remainingTime
# For asterisk to read each number
def calcDec(self, dectime):
numCategory = 10
while True:
if (dectime // numCategory) == 0:
numCategory = int(numCategory / 10)
break
else:
numCategory = numCategory * 10
if dectime >= numCategory and dectime > 20:
return 'digits/' + str((dectime // numCategory) * numCategory) + " " + str(self.calcDec(dectime % numCategory))
else:
return 'digits/' + str(dectime)
def getAsteriskPrint(self):
asteriskRemaining = self.calcDec(int(str(self.remainingTime).split('.')[0]))
if self.remainingTime > 0:
asteriskPrint = '&'.join(('prepaid-you-have', asteriskRemaining, 'minutes')).replace(' ', '&')
else:
asteriskPrint = 'prepaid-zero-balance'
return asteriskPrint
# Constants for DialPlan
#try:
# # Read the freeminutes from a text file every day. This requres
# # an other application to write everyday the free minutes to a
# # file "freemin.txt" and start counting only for today's minutes.
# with open('freemin.txt', 'r') as f:
# result_from_nova = int(f.readline()) * 60
# totalFreeTime = result_from_nova #Free seconds given by provider
# startDay = nowDay # The Month Day that starts counting from
@click.command()
@click.option('--sipfilter', default='vodafone', help='The SIP to filter')
@click.option('--freetime', default=18000, help='The free time provided by the provider')
@click.option('--startday', default=1, help='Start of the billing cycle')
@click.option('--extratime', default=15, help='Extra time to compensate the lack of answer detection')
@click.option('--climatch', default="69[0-9]+", help='The CLI to filter (RegExpr)')
def main(sipfilter, freetime, startday, extratime, climatch):
""" Shows the remaining time based on the Master.csv file of Asterisk """
AsteriskShowLimit(sipFilter=sipfilter, freeTime=freetime, startDay=startday, extraTime=extratime, cliMatch=climatch)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment