Coder Social home page Coder Social logo

emxsys / callattendant Goto Github PK

View Code? Open in Web Editor NEW
110.0 9.0 38.0 14.54 MB

A python-based automated call attendant, call blocker, and voice messaging system running on a Raspberry Pi. Screens callers and block robocalls and scams with a low-cost Raspberry Pi and modem.

Home Page: https://emxsys.github.io/callattendant/

License: MIT License

Python 78.80% HTML 18.23% Shell 0.26% CSS 2.71%
python uml telephony modem raspberry-pi call-blocker voice-messages flask call-screener rational-unified-process

callattendant's People

Contributors

emxsys avatar zomgreg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

callattendant's Issues

Add voice messaging menu

Add a voice messaging menu that responds to the caller's touch-tone key presses, for example:

  • "Press 1 to leave a message"
  • "Press 0 to hang up"

Error when adding a user to whitelist

192.168.1.106 - - [03/Aug/2020 17:44:39] "GET /manage_caller/3 HTTP/1.1" 200 -
Adding LNAME FNAME to whitelist
[2020-08-03 17:44:41,309] ERROR in app: Exception on /manage_caller/3 [POST]
Traceback (most recent call last):
File "/home/pi/p3/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/home/pi/p3/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/pi/p3/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/pi/p3/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/pi/p3/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/home/pi/p3/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functionsrule.endpoint
File "/home/pi/projects/callattendant/src/userinterface/webapp.py", line 236, in manage_caller
whitelist = Whitelist(get_db())

Package and make installable via PyPi

As a user of callattendant, I want to be able to install this software via something like pip install callattendant and have the necessary dependencies automatically installed and be presented with a nice web interface at the end.

Things that should be done first:

  • 1.conf.py
  • 2. Port to python3 #36
  • 3. Create setup.py

Generate end-user documentation in the Wiki

Create the User Guide in this project's Wiki.
Reserve the Wiki for the end-user documentation. Developer docs are in the README.

  • Add link to the User Guide to the callattendant's nav-bar branding.
  • Add a link to the User Guide to the README.
  • Add Installation instructions including service setups for Linux/Raspberry Pi
  • Add Configuration instructions
  • Add Hardware Interface instructions

Record voice message

Add ability to record messages from callers. The messages should be uniquely identify to caller records in the call log.

Add a Messages table for tracking voice messages

A Messages table is need to enhance the handling of voices messages. It should do the following:

  • Manage the played/unplayed status of voice messages
  • Provide high performance (via joins) when displaying call lists with associated voice messages
  • Future: Possibly hold the message data in a Blob field.
CREATE TABLE IF NOT EXISTS Message (
                    MessageID INTEGER PRIMARY KEY AUTOINCREMENT,
                    CallLogID INTEGER,
                    Played BOOLEAN DEFAULT 0 NOT NULL CHECK (Played IN (0,1)),
                    Filename TEXT,
                    DateTime TEXT,
                    FOREIGN KEY(CallLogID) REFERENCES CallLog(CallLogID));

Refactor Modem class

Refactor the Modem class into an BasicModem base class and a USRobotics5637Modem derived class.

  • Base class has serial port and send, receive responsibilities.

  • Subclass has call handling responsibilities

  • Eliminate coupling from Modem to CallAttendant; use a callback instead.

Validate configuration items

Validate the configuration after loading. The validation process should insure that all the default configuration items have permissible values. A RuntimeError should be raised otherwise.

Also, the configuration should always be printed to the standard output, not just when config["DEBUG"] is True. This will be helpful in the future when debugging an error or providing support. The configuration dump could/should be included in bug-related issues. (Issue templates?)

Permitted/Blocked name should override CID name in Call Log

The Call Log is suppose to display the name from either the Permitted or Blocked table, whichever was used, if used. In the case of permitted calls, this allows friendly names to override the default CID names. In the case of blocked calls, this allows a corrective display in the case of spoofed names.

Front end fails to initialize due to call to missing table field.

Error:

Unhandled exception in thread started by <function flaskThread at 0x737973f0>
Traceback (most recent call last):
  File "/home/pi/testing/callattendant/src/userinterface/webapp.py", line 123, in flaskThread
    call_details()
  File "/home/pi/testing/callattendant/src/userinterface/webapp.py", line 62, in call_details
    result_set = screening.utils.query_db(get_db(), query, arguments)
  File "/home/pi/testing/callattendant/src/screening/utils.py", line 29, in query_db
    cur = db.execute(query, args)
sqlite3.OperationalError: no such column: b.Reason

Likely this is because the whitelist table contains no Reason field.

I will submit a PR with what I think is the fix.

Improve web user interface

  • Add Dashboard page #41
  • Add CRUD support to Permitted page #38
  • Add CRUD support to Blocked page #39
  • Add voice message symbols/buttons to Call Log page
  • Add block caller buttons to Messages page
  • Improve mobile/ responsive layout
  • Add Call History page #24
  • Enable context menu on Call Log (consider: manage caller, play voice message)

Divide by zero on new install.

There is a divide by 0 that happens on a clean install:

    percent_blocked = blocked / total * 100          
ZeroDivisionError: division by zero  

Because there have been 0 total calls. Pull request is ready.

Create flexible and robust application configuration

Refactor configuration handling to make it robust by including:

  • Default configuration if no config file
  • Accepting an external config file via the command line
  • Providing an example config file
  • Documenting the command line

Config setting to include:

  • Call blocking modes
  • Regex patterns for names
  • Regex pattern for numbers
  • Voice messaging features
  • Phone number formatting

Embellish Call Log web interface

  • Highlight whitelisted and blacklisted callers
  • Periodically refresh page
  • Add action taken
  • Add capability to add caller to whitelist or blacklist
  • Add navigation links between the call log, whitelist and blacklist pages.

Enable Voice Mail for screened and permitted callers

Add voice messaging capabilities and options for all callers:

  • Add options to enable voice mail for permitted and screen callers
  • Configure answer after n number of rings
  • Add button(s) to reset the "unplayed" status of a voice message

FYI: In North America, the standard ring cadence is "2-4", or two seconds of ringing followed by four seconds of silence (33% Duty Cycle). This information could be used to implement a time-based wait system before pickup. E.g., to wait for for n rings would be time.sleep( n * 6)

Examples:

  • 'Screened' calls could be intercepted with the general greeting and then sent to voice mail
  • 'Permitted' calls could ring n times, allowing you to answer, before being sent to voice mail

Add pagination to the call log

Add pagination to the call_details.htm to reduce the overhead of displaying multiple years of call data on a single page.

Add Manage Caller page

Add a page to manage a caller's inclusion in the permitted and/or blocked numbers lists. Re:; #13

Consider adding a link to the caller's call history page (TBD).

Refine Call Log

Improve the Call Log:

  • Add "new message" | "message waiting" indicator
  • Add search/filter capability
  • Refine the layout

Part of #40

System sometimes fails to answer call

Sometimes the system fails to answer an incoming call if the previous caller hangs up in the middle of the Voice Mail menu.

Potential workaround(s):

  • Configure system not to record messages:
BLOCKED_ACTIONS = ("greeting", )
  • Configure system to record messages without Voice Mail menu.
BLOCKED_ACTIONS = (""record_message")
# or
BLOCKED_ACTIONS = ("greeting", "record_message")

Improve web interface

Prototype web interface subsystem:

  • Display whitelist
  • Display blacklist
  • Embellish call log

Add a "New Messages Waiting" LED indicator

Create an LED indicator that indicates that new voice messages are waiting.

  • Consider adding a 7-segment LED to indicate the number of message waiting.
  • Will need a table to manage the read/unread status of messages. (#59)
  • Consider joining the new table with the call log table to show a message indicator for the calls in the Call Log page

Play Message modal dialog should set message played status

The Message modal dialog on all associated pages should update the played status of the played voice message.

  • Requires upgrading from JQuery "slim" version to acquire AJAX capabilities

  • Consider using a common "play message" Flask template

  • Also, add a Delete button to the dialog.

Add Call History page

Add a page to display the call history for a phone number.

Consider adding a filter/search to the Call Log.

Prototype candidate architecture

Exhibit and demonstrate, the candidate architecture against some of the primary scenarios:

  • Screen call
  • Log call
  • Block call
  • View call log

Add ACTION column to call log table

Add an ACTION column to the call log table to capture the call blocker's action taken. This field records the call blocker history. Currently the history is inferred by the existence of the number in whitelist and blacklist tables. But those associations can be temporal: if they change the history is lost.

Possible values for the field include:

  • Blocked
  • Permitted
  • Screened

Add Dashboard page

Add a Dashboard page to be used as the root route (index.html). The dashboard would include:

  • Metrics
  • Recent calls (short list)
  • Top callers (permitted/screened and blocked; names, numbers and counts)
  • Number of callers last 14 days (stacked bar graph - chart.js)
  • Voice message notifications

flask_paginate module not found when run as a service

The following output from `sudo journalctl --follow -u callattendant.service shows the error:

Jul 31 01:14:28 pi-blocker systemd[1]: Started Call Attendant.
Jul 31 01:14:30 pi-blocker python[9919]: Traceback (most recent call last):
Jul 31 01:14:30 pi-blocker python[9919]:   File "/home/pi/callattendant/src/callattendant.py", line 32, in <module>
Jul 31 01:14:30 pi-blocker python[9919]:     import userinterface.webapp as webapp
Jul 31 01:14:30 pi-blocker python[9919]:   File "/home/pi/callattendant/src/userinterface/webapp.py", line 33, in <module>
Jul 31 01:14:30 pi-blocker python[9919]:     from flask_paginate import Pagination, get_page_args
Jul 31 01:14:30 pi-blocker python[9919]: ImportError: No module named flask_paginate
Jul 31 01:14:30 pi-blocker systemd[1]: callattendant.service: Main process exited, code=exited, status=1/FAILURE
Jul 31 01:14:30 pi-blocker systemd[1]: callattendant.service: Unit entered failed state.
Jul 31 01:14:30 pi-blocker systemd[1]: callattendant.service: Failed with result 'exit-code'.

callattendate.service Unit File:

[Unit]
Description=Call Attendant
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/bin/python /home/pi/callattendant/src/callattendant.py
WorkingDirectory=/home/pi/callattendant/src
Restart=on-abort

[Install]
WantedBy=multi-user.target

flask_paginate was installed via the requirements.txt file. pip show flask_paginate shows the modules.

Modem play audio (wav file) fails

After the port to Python3, the Modem class fails to play the audio file. The system stalls.
Following is the output of the Modem unit tests after pressing Ctrl-C

(python3) pi@hamshack:~/src/callattendant/src $ python hardware/modem.py
[Configuration]
  BLOCKED_ACTIONS = ('play_message',)
  BLOCKED_MESSAGE_FILE = hardware/blocked.wav
  BLOCK_ENABLED = True
  BLOCK_NAME_PATTERNS = {'V[0-9]{15}': 'Telemarketer Caller ID'}
  BLOCK_NUMBER_PATTERNS = {}
  DATABASE = callattendant.db
  DEBUG = False
  DEBUGs = True
  ENV = production
  ROOT_PATH = /home/pi/src/callattendant/src
  SCREENING_MODE = ('whitelist', 'blacklist')
  TESTING = False
Running Unit Tests....
Modem COM Port is: /dev/ttyACM0
Assert factory reset
Assert display modem settings
Assert put modem into voice mode.
Assert set compression method and sampling rate specifications.
Assert put modem into TAD mode.
Assert put modem into data transmit state.
Assert cancel data transmit state.
Play Audio Msg - Start
Play Audio Msg - playing wav file
^CTraceback (most recent call last):
  File "hardware/modem.py", line 563, in <module>
    sys.exit(test(config, phone_ringing, handle_caller))
  File "hardware/modem.py", line 534, in test
    modem.play_audio(os.path.join(currentdir, "sample.wav"))
  File "hardware/modem.py", line 234, in play_audio
    time.sleep(.12)
KeyboardInterrupt

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.