]> OzVa Git service - conf-dialer/commitdiff
made layout more flask friendly
authorMax Value <greenwoodw50@gmail.com>
Thu, 25 Dec 2025 22:10:38 +0000 (22:10 +0000)
committerMax Value <greenwoodw50@gmail.com>
Thu, 25 Dec 2025 22:10:38 +0000 (22:10 +0000)
.gitignore
Makefile [new file with mode: 0644]
dialer.py [new file with mode: 0755]
main.py [deleted file]
setup.py [new file with mode: 0644]
test.py [deleted file]

index 311cfd867e0b599c6f8e8872225927ff027dbf66..fa9cbd21c22b946bfb579f8bbd27c09f2184c84e 100644 (file)
@@ -1,2 +1,4 @@
 .venv/
+__pycache__/
+dialer.egg-info/
 secrets.json
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..1677284
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+all : .venv/touchfile
+       .venv/bin/python -m flask --app dialer run
+
+.venv/touchfile : requirements.txt
+       python -m venv .venv
+       .venv/bin/python -m pip install -r requirements.txt
+       touch .venv/touchfile
diff --git a/dialer.py b/dialer.py
new file mode 100755 (executable)
index 0000000..928960d
--- /dev/null
+++ b/dialer.py
@@ -0,0 +1,328 @@
+#!.venv/bin/python
+
+from werkzeug.security import generate_password_hash, check_password_hash
+from flask import Flask, request, render_template, jsonify
+from requests.auth import HTTPBasicAuth as requests_auth
+from panoramisk.call_manager import CallManager
+from flask_socketio import SocketIO, emit
+from flask_httpauth import HTTPBasicAuth
+from panoramisk import Manager
+import threading
+import requests
+import asyncio
+import json
+import os
+
+from websockets.sync.client import connect
+
+app = Flask(__name__)
+auth = HTTPBasicAuth()
+socketio = SocketIO(app)
+
+
+
+# ==============================================================================
+# SETUP
+
+# get the player data ready
+with open(f"{app.root_path}/players.json", "r", encoding="utf-8") as f:
+       players = json.loads(f.read())
+
+# get the secrets ready
+with open(f"{app.root_path}/secrets.json", "r", encoding="utf-8") as f:
+       users_raw = json.loads(f.read())
+users = {k: generate_password_hash(v) for (k, v) in users_raw.items()}
+
+@auth.verify_password
+def verify_password(username, password):
+    if username in users and \
+            check_password_hash(users.get(username), password):
+        return username
+
+
+
+# ==============================================================================
+# FRONTEND
+
+@app.route("/", methods=["GET", "POST"])
+@auth.login_required
+def main():
+       data = {
+               "players": players,
+               "sounds": [x.rsplit(".", maxsplit=1)[0] for x in os.listdir(f"{app.root_path}/sounds")],
+               "admin": "+447594768180"
+               }
+
+       return render_template("panel.html", data=data)
+
+
+
+# ==============================================================================
+# UTILS
+
+async def get_channel(number):
+       manager = Manager.from_config(f"{app.root_path}/config.ini")
+       await manager.connect()
+
+       callers = await manager.send_action({
+               'Action': 'ConfbridgeList',
+               'Conference': 'blood',
+       })
+
+       channel = None
+
+       if type(callers) == list:
+               for message in callers:
+                       channel_num = message.get("CallerIDNum") #"Channel"
+                       if channel_num == number:
+                               channel = message.channel
+
+       manager.close()
+
+       return channel
+
+
+
+# ==============================================================================
+# DIALPLAN
+
+@app.route("/call", methods=["GET", "POST"])
+@auth.login_required
+async def call():
+       number = request.json["number"]
+
+       manager = Manager.from_config(f"{app.root_path}/config.ini")
+       await manager.connect()
+
+       phonecall = await manager.send_action({
+               "Action": "Originate",
+               "Channel": f"PJSIP/{number}@gotrunk",
+               "Exten": "blood",
+               "Context": "from-internal",
+               "Priority": "1",
+               # "Application": <value>,
+               # "Data": <value>,
+               # "Timeout": 10,
+               "CallerID": "Departed",
+               "Variable": f"CALLERID(num)={number}",
+               # "Account": <value>,
+               # "EarlyMedia": <value>,
+               "Async": "true",
+               # "Codecs": <value>,
+               # "ChannelId": <value>,
+               # "OtherChannelId": <value>,
+               # "PreDialGoSub": <value>
+               })
+
+       manager.close()
+
+       return "", 200
+
+
+@app.route("/kick", methods=["GET", "POST"])
+@auth.login_required
+async def kick():
+       number = request.json["number"]
+
+       if number == "participants":
+               channel = number
+       else:
+               channel = await get_channel(number)
+
+       if channel is None:
+               return f"Caller is not connected ({number})", 422
+
+       manager = Manager.from_config(f"{app.root_path}/config.ini")
+       await manager.connect()
+
+       result = await manager.send_action({
+               "Action": "ConfbridgeKick",
+               "Conference": "blood",
+               "Channel": channel
+               })
+
+       manager.close()
+       return "", 200
+
+
+@app.route("/mute", methods=["GET", "POST"])
+@auth.login_required
+async def mute():
+       number = request.json["number"]
+
+       if number == "participants":
+               channel = number
+       else:
+               channel = await get_channel(number)
+
+       if channel is None:
+               return f"Caller is not connected ({number})", 422
+
+       manager = Manager.from_config(f"{app.root_path}/config.ini")
+       await manager.connect()
+
+       result = await manager.send_action({
+               "Action": "ConfbridgeMute",
+               "Conference": "blood",
+               "Channel": channel
+               })
+
+       manager.close()
+       return "", 200
+
+
+@app.route("/unmute", methods=["GET", "POST"])
+@auth.login_required
+async def unmute():
+       number = request.json["number"]
+
+       if number == "participants":
+               channel = number
+       else:
+               channel = await get_channel(number)
+
+       if channel is None:
+               return "Caller is not connected", 200
+
+       manager = Manager.from_config(f"{app.root_path}/config.ini")
+       await manager.connect()
+
+       result = await manager.send_action({
+               "Action": "ConfbridgeUnmute",
+               "Conference": "blood",
+               "Channel": channel
+               })
+
+       manager.close()
+       return "", 200
+
+
+@app.route("/play", methods=["GET", "POST"])
+@auth.login_required
+async def play():
+       path = request.json["path"]
+
+       manager = Manager.from_config(f"{app.root_path}/config.ini")
+       await manager.connect()
+
+       phonecall = await manager.send_action({
+               "Action": "Originate",
+               "Channel": "Local/bloodadmin@from-internal",
+               "Application": "Playback",
+               "Data": f"/home/will/{path}",
+               "Async": "true",
+               "CallerID": f"file_{path}"
+               })
+
+       manager.close()
+
+       return "", 200
+
+
+@app.route("/stopall")
+@auth.login_required
+async def stopall():
+       manager = Manager.from_config(f"{app.root_path}/config.ini")
+       await manager.connect()
+
+       callers = await manager.send_action({
+               'Action': 'ConfbridgeList',
+               'Conference': 'blood',
+       })
+
+       if type(callers) == list:
+               for message in callers:
+                       if message.CallerIDName[:4] == "file":
+                               result = await manager.send_action({
+                                       "Action": "ConfbridgeKick",
+                                       "Conference": "blood",
+                                       "Channel": message.channel
+                                       })
+
+       manager.close()
+       return "", 200
+
+
+
+# ==============================================================================
+# EVENTS
+
+watcher = Manager.from_config(f"{app.root_path}/config.ini")
+
+def start_watch():
+       loop = asyncio.new_event_loop()
+       watcher.loop = loop
+
+       print(" * Event watcher started")
+       watcher.connect(run_forever=True)
+
+
+def send_emit(data):
+       with app.test_request_context('/'):
+               emit("status", data, json=True, broadcast=True, namespace="/")
+
+
+@watcher.register_event('DialState')  # Register all events
+async def dialstate_callback(manager, message):
+       send_emit({
+                       "number": message.DestCallerIDNum,
+                       "status": "Ringing",
+                       "mute": True
+               })
+
+
+@watcher.register_event('ConfbridgeJoin')  # Register all events
+async def confbridgejoin_callback(manager, message):
+       if message.CallerIDName[:4] == "file":
+               number = message.CallerIDName[5:]
+       else:
+               number = message.CallerIDNum
+
+       send_emit({
+                       "number": number,
+                       "status": "Connected",
+                       "mute": message.Muted == "yes"
+               })
+
+
+@watcher.register_event('ConfbridgeLeave')  # Register all events
+async def confbridgeleave_callback(manager, message):
+       if message.CallerIDName[:4] == "file":
+               number = message.CallerIDName[5:]
+       else:
+               number = message.CallerIDNum
+
+       send_emit({
+                       "number": number,
+                       "status": "Disconnected",
+                       "mute": True
+               })
+
+
+@watcher.register_event('ConfbridgeMute')  # Register all events
+async def confbridgemute_callback(manager, message):
+       send_emit({
+                       "number": message.CallerIDNum,
+                       "status": "Connected",
+                       "mute": True
+               })
+
+
+@watcher.register_event('ConfbridgeUnmute')  # Register all events
+async def confbridgeunmute_callback(manager, message):
+       send_emit({
+                       "number": message.CallerIDNum,
+                       "status": "Connected",
+                       "mute": False
+               })
+
+
+
+# ==============================================================================
+
+if __name__ == "__main__":
+       # start the event watch manager
+       thread = threading.Thread(target=start_watch, daemon=True)
+       thread.start()
+
+       socketio.run(app, host='127.0.0.1', port=8000, debug=True)
diff --git a/main.py b/main.py
deleted file mode 100755 (executable)
index 3156f21..0000000
--- a/main.py
+++ /dev/null
@@ -1,329 +0,0 @@
-#!.venv/bin/python
-
-from werkzeug.security import generate_password_hash, check_password_hash
-from flask import Flask, request, render_template, jsonify
-from requests.auth import HTTPBasicAuth as requests_auth
-from panoramisk.call_manager import CallManager
-from flask_socketio import SocketIO, emit
-from flask_httpauth import HTTPBasicAuth
-from panoramisk import Manager
-import threading
-import requests
-import asyncio
-import json
-import os
-
-from websockets.sync.client import connect
-
-app = Flask(__name__)
-auth = HTTPBasicAuth()
-socketio = SocketIO(app)
-
-
-
-# ==============================================================================
-# SETUP
-
-# get the player data ready
-with open(f"{app.root_path}/players.json", "r", encoding="utf-8") as f:
-       players = json.loads(f.read())
-
-# get the secrets ready
-with open(f"{app.root_path}/secrets.json", "r", encoding="utf-8") as f:
-       users_raw = json.loads(f.read())
-users = {k: generate_password_hash(v) for (k, v) in users_raw.items()}
-basic = requests_auth('controller', users_raw['controller'])
-
-@auth.verify_password
-def verify_password(username, password):
-    if username in users and \
-            check_password_hash(users.get(username), password):
-        return username
-
-
-
-# ==============================================================================
-# FRONTEND
-
-@app.route("/", methods=["GET", "POST"])
-@auth.login_required
-def main():
-       data = {
-               "players": players,
-               "sounds": [x.rsplit(".", maxsplit=1)[0] for x in os.listdir(f"{app.root_path}/sounds")],
-               "admin": "+447594768180"
-               }
-
-       return render_template("panel.html", data=data)
-
-
-
-# ==============================================================================
-# UTILS
-
-async def get_channel(number):
-       manager = Manager.from_config(f"{app.root_path}/config.ini")
-       await manager.connect()
-
-       callers = await manager.send_action({
-               'Action': 'ConfbridgeList',
-               'Conference': 'blood',
-       })
-
-       channel = None
-
-       if type(callers) == list:
-               for message in callers:
-                       channel_num = message.get("CallerIDNum") #"Channel"
-                       if channel_num == number:
-                               channel = message.channel
-
-       manager.close()
-
-       return channel
-
-
-
-# ==============================================================================
-# DIALPLAN
-
-@app.route("/call", methods=["GET", "POST"])
-@auth.login_required
-async def call():
-       number = request.json["number"]
-
-       manager = Manager.from_config(f"{app.root_path}/config.ini")
-       await manager.connect()
-
-       phonecall = await manager.send_action({
-               "Action": "Originate",
-               "Channel": f"PJSIP/{number}@gotrunk",
-               "Exten": "blood",
-               "Context": "from-internal",
-               "Priority": "1",
-               # "Application": <value>,
-               # "Data": <value>,
-               # "Timeout": 10,
-               "CallerID": "Departed",
-               "Variable": f"CALLERID(num)={number}",
-               # "Account": <value>,
-               # "EarlyMedia": <value>,
-               "Async": "true",
-               # "Codecs": <value>,
-               # "ChannelId": <value>,
-               # "OtherChannelId": <value>,
-               # "PreDialGoSub": <value>
-               })
-
-       manager.close()
-
-       return "", 200
-
-
-@app.route("/kick", methods=["GET", "POST"])
-@auth.login_required
-async def kick():
-       number = request.json["number"]
-
-       if number == "participants":
-               channel = number
-       else:
-               channel = await get_channel(number)
-
-       if channel is None:
-               return f"Caller is not connected ({number})", 422
-
-       manager = Manager.from_config(f"{app.root_path}/config.ini")
-       await manager.connect()
-
-       result = await manager.send_action({
-               "Action": "ConfbridgeKick",
-               "Conference": "blood",
-               "Channel": channel
-               })
-
-       manager.close()
-       return "", 200
-
-
-@app.route("/mute", methods=["GET", "POST"])
-@auth.login_required
-async def mute():
-       number = request.json["number"]
-
-       if number == "participants":
-               channel = number
-       else:
-               channel = await get_channel(number)
-
-       if channel is None:
-               return f"Caller is not connected ({number})", 422
-
-       manager = Manager.from_config(f"{app.root_path}/config.ini")
-       await manager.connect()
-
-       result = await manager.send_action({
-               "Action": "ConfbridgeMute",
-               "Conference": "blood",
-               "Channel": channel
-               })
-
-       manager.close()
-       return "", 200
-
-
-@app.route("/unmute", methods=["GET", "POST"])
-@auth.login_required
-async def unmute():
-       number = request.json["number"]
-
-       if number == "participants":
-               channel = number
-       else:
-               channel = await get_channel(number)
-
-       if channel is None:
-               return "Caller is not connected", 200
-
-       manager = Manager.from_config(f"{app.root_path}/config.ini")
-       await manager.connect()
-
-       result = await manager.send_action({
-               "Action": "ConfbridgeUnmute",
-               "Conference": "blood",
-               "Channel": channel
-               })
-
-       manager.close()
-       return "", 200
-
-
-@app.route("/play", methods=["GET", "POST"])
-@auth.login_required
-async def play():
-       path = request.json["path"]
-
-       manager = Manager.from_config(f"{app.root_path}/config.ini")
-       await manager.connect()
-
-       phonecall = await manager.send_action({
-               "Action": "Originate",
-               "Channel": "Local/bloodadmin@from-internal",
-               "Application": "Playback",
-               "Data": f"/home/will/{path}",
-               "Async": "true",
-               "CallerID": f"file_{path}"
-               })
-
-       manager.close()
-
-       return "", 200
-
-
-@app.route("/stopall")
-@auth.login_required
-async def stopall():
-       manager = Manager.from_config(f"{app.root_path}/config.ini")
-       await manager.connect()
-
-       callers = await manager.send_action({
-               'Action': 'ConfbridgeList',
-               'Conference': 'blood',
-       })
-
-       if type(callers) == list:
-               for message in callers:
-                       if message.CallerIDName[:4] == "file":
-                               result = await manager.send_action({
-                                       "Action": "ConfbridgeKick",
-                                       "Conference": "blood",
-                                       "Channel": message.channel
-                                       })
-
-       manager.close()
-       return "", 200
-
-
-
-# ==============================================================================
-# EVENTS
-
-watcher = Manager.from_config(f"{app.root_path}/config.ini")
-
-def start_watch():
-       loop = asyncio.new_event_loop()
-       watcher.loop = loop
-
-       print(" * Event watcher started")
-       watcher.connect(run_forever=True)
-
-
-def send_emit(data):
-       with app.test_request_context('/'):
-               emit("status", data, json=True, broadcast=True, namespace="/")
-
-
-@watcher.register_event('DialState')  # Register all events
-async def dialstate_callback(manager, message):
-       send_emit({
-                       "number": message.DestCallerIDNum,
-                       "status": "Ringing",
-                       "mute": True
-               })
-
-
-@watcher.register_event('ConfbridgeJoin')  # Register all events
-async def confbridgejoin_callback(manager, message):
-       if message.CallerIDName[:4] == "file":
-               number = message.CallerIDName[5:]
-       else:
-               number = message.CallerIDNum
-
-       send_emit({
-                       "number": number,
-                       "status": "Connected",
-                       "mute": message.Muted == "yes"
-               })
-
-
-@watcher.register_event('ConfbridgeLeave')  # Register all events
-async def confbridgeleave_callback(manager, message):
-       if message.CallerIDName[:4] == "file":
-               number = message.CallerIDName[5:]
-       else:
-               number = message.CallerIDNum
-
-       send_emit({
-                       "number": number,
-                       "status": "Disconnected",
-                       "mute": True
-               })
-
-
-@watcher.register_event('ConfbridgeMute')  # Register all events
-async def confbridgemute_callback(manager, message):
-       send_emit({
-                       "number": message.CallerIDNum,
-                       "status": "Connected",
-                       "mute": True
-               })
-
-
-@watcher.register_event('ConfbridgeUnmute')  # Register all events
-async def confbridgeunmute_callback(manager, message):
-       send_emit({
-                       "number": message.CallerIDNum,
-                       "status": "Connected",
-                       "mute": False
-               })
-
-
-
-# ==============================================================================
-
-if __name__ == "__main__":
-       # start the event watch manager
-       thread = threading.Thread(target=start_watch, daemon=True)
-       thread.start()
-
-       socketio.run(app, host='127.0.0.1', port=8000, debug=True)
diff --git a/setup.py b/setup.py
new file mode 100644 (file)
index 0000000..faf0fdf
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,5 @@
+from distutils.core import setup
+setup(name='dialer',
+       version='1.0',
+       py_modules=['dialer'],
+       )
diff --git a/test.py b/test.py
deleted file mode 100644 (file)
index f5647a6..0000000
--- a/test.py
+++ /dev/null
@@ -1,28 +0,0 @@
-import asyncio
-from panoramisk import Manager
-
-async def extension_status():
-    manager = Manager(loop=asyncio.get_event_loop(),
-                      host='127.0.0.1', port=5038,
-                      username='asterisk', secret='test')
-
-    await manager.connect()
-    action = {
-        'Action': 'ConfbridgeList',
-        'Conference': 'blood',
-    }
-
-    extension = await manager.send_action(action)
-    print(extension)
-    manager.close()
-
-
-def main():
-    loop = asyncio.get_event_loop()
-    loop.run_until_complete(extension_status())
-    loop.close()
-
-
-if __name__ == '__main__':
-    main()
-