This commit is contained in:
Сергей Филимонов 2024-06-17 18:57:08 +07:00
parent e03a34c47a
commit fc75f83926
45 changed files with 1181 additions and 431 deletions

View File

@ -64,18 +64,41 @@ def blacklist():
call = bl.find().sort('_id') call = bl.find().sort('_id')
return render_template("blacklist.html", call=call) if rep == False else render_template("repair.html") return render_template("blacklist.html", call=call) if rep == False else render_template("repair.html")
@app.route("/test")
def ttt():
res = []
for p in request.environ:
try:
res.append(p + " = " + request.environ[p])
except:
pass
# #"<br>".join(request.environ)
return str(res)
@app.route("/work/<uuid>")
def work_uuid(uuid):
coll.update_one({"uuid": uuid}, {"$set": {"status": "INWORK"}})
call = coll.find({"uuid": uuid})
return render_template("work.html", call=call) if rep == False else render_template("repair.html")
# API # API
@app.route("/api/v1/call/set/", methods=["POST"]) @app.route("/api/v1/call/set/", methods=["POST"])
def call_put(): def call_put():
print(request.form) # print(request.form)
if request.form["act"] == "delete": if request.form["act"] == "delete":
coll.update_many({"uuid": request.form["uuid"], "status": "RECALL_FALSE"}, { coll.update_many({"uuid": request.form["uuid"], "status": "RECALL_FALSE"}, {
"$set": {"status": "DELETED"}}) "$set": {"status": "DELETED"}})
return redirect("/falserecall") return redirect("/falserecall")
@app.route("/api/v1/work/", methods=["POST"])
def work():
dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
coll.update_one({"uuid": request.form["uuid"]}, {"$set": {"status": "RECALL_" + str(request.form["recall"]).upper(), "dt": dt}})
return redirect("/")
@app.route("/api/v1/blacklist/add/<number>", methods=["POST"]) @app.route("/api/v1/blacklist/add/<number>", methods=["POST"])
def blacklist_put(number): def blacklist_put(number):
insdict = {"_id": number, "desc": datetime.datetime.now()} insdict = {"_id": number, "desc": datetime.datetime.now()}

View File

@ -69,13 +69,6 @@
<a href="/truerecall">Перезвонили успешно</a> <a href="/truerecall">Перезвонили успешно</a>
<a href="/falserecall">Перезвонили безуспешно</a> <a href="/falserecall">Перезвонили безуспешно</a>
</div> </div>
<!-- <div>
<form name="search" action="/web/call/find/" method="get" class="search">
<label class="search_label">Поиск</label>
<input class="search_text" type="text" name="client">
<input class="search_btn" type="submit" title="Найти">
</form>
</div> -->
<table> <table>
<thead> <thead>

View File

@ -75,22 +75,11 @@
<div class="inl"><a href="/truerecall">Перезвонили успешно</a></div> <div class="inl"><a href="/truerecall">Перезвонили успешно</a></div>
<div class="inl-active"><a href="/falserecall">Перезвонили безуспешно</a></div> <div class="inl-active"><a href="/falserecall">Перезвонили безуспешно</a></div>
</div> </div>
<!-- <div>
<form name="search" action="/web/call/find/" method="get" class="search">
<label class="search_label">Поиск</label>
<input class="search_text" type="text" name="client">
<input class="search_btn" type="submit" title="Найти">
</form>
</div> -->
<table> <table>
<thead> <thead>
<tr> <tr>
<th>Номер клиента</th> <th>Номер клиента</th>
<th>Кол-во попыток</th>
<th>Дата и время</th> <th>Дата и время</th>
<th>Продолжительность</th>
<th>Оператор</th>
<th>Запись</th>
<th>Действие</th> <th>Действие</th>
</tr> </tr>
</thead> </thead>
@ -105,16 +94,7 @@
{% else %} {% else %}
<td>{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}</td> <td>{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}</td>
{% endif %} {% endif %}
<td>{{ c.count_try }}</td> <td>{{ c.dt }}</td>
<td>{{ c.time }}</td>
<td>{{ c.answered_duration // 60 }}:{{ "{:02}".format(c.answered_duration % 60) }}</td>
<td>{{ c.operator }}</td>
<td>
{% if c.has_record == true: %}
<audio src="{{ c.record_url }}" type="audio/mp3" preload="none" controls>Запись</audio>
{% else %}
Отсутствует
{% endif %}
<td style="vertical-align: middle;"> <td style="vertical-align: middle;">
<div> <div>
<form action="/api/v1/call/set/" method="post" style="border: 0;"> <form action="/api/v1/call/set/" method="post" style="border: 0;">

View File

@ -63,7 +63,10 @@
} }
.inl {display: inline;} .inl {
display: inline;
}
.inl-active { .inl-active {
display: inline; display: inline;
background-color: #FFD300; background-color: #FFD300;
@ -79,11 +82,6 @@
</div> </div>
<div> <div>
<!-- <form name="search" action="/web/call/find/" method="get" class="search">
<label class="search_label">Поиск</label>
<input class="search_text" type="text" name="client">
<input class="search_btn" type="submit" title="Найти">
</form> -->
</div> </div>
@ -102,11 +100,18 @@
{% if c.mkt_phone == "83912051045": %} {% if c.mkt_phone == "83912051045": %}
<td> <td>
<font color="#C30000">{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], <font color="#C30000">
c.client[7:11]) }}</font> <a href="/work/{{ c.uuid }}">
{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}
</a>
</font>
</td> </td>
{% else %} {% else %}
<td>{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}</td> <td>
<a href="/work/{{ c.uuid }}">
{{ "%s %s %s %s" |format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}
</a>
</td>
{% endif %} {% endif %}
<td>{{ c.time }} {{ c.important }}</td> <td>{{ c.time }} {{ c.important }}</td>
<td>{{ c.answered_duration // 60 }}:{{ "{:02}".format(c.answered_duration % 60) }}</td> <td>{{ c.answered_duration // 60 }}:{{ "{:02}".format(c.answered_duration % 60) }}</td>

View File

@ -0,0 +1,104 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='main.css') }}">
<title>Перезвонили успешно</title>
</head>
<style type="text/css" media="screen">
table {
width: 100%;
margin-bottom: 20px;
border: 5px solid #fff;
border-top: 5px solid #fff;
border-bottom: 3px solid #fff;
border-collapse: collapse;
outline: 3px solid #ffd300;
font-size: 15px;
background: #fff !important;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
table th {
font-weight: bold;
padding: 7px;
background: #ffd300;
border: none;
text-align: left;
font-size: 15px;
border-top: 3px solid #fff;
border-bottom: 3px solid #ffd300;
}
table td {
padding: 7px;
border: none;
border-top: 3px solid #fff;
border-bottom: 3px solid #fff;
font-size: 15px;
}
table tbody tr:nth-child(even) {
background: #f8f8f8 !important;
}
a {
font-size: large;
font-family: Verdana, Geneva, Tahoma, sans-serif;
color: #7A1E99;
padding-right: 50px;
}
header {
height: 50px;
vertical-align: middle;
}
form {
height: 40px;
}
.inl {display: inline;}
.inl-active {
display: inline;
background-color: #FFD300;
}
</style>
<body>
<div>
<div class="inl"><a href="/answer">Входящий вызов принят</a></div>
<div class="inl"><a href="/notanswer">Входящий вызов не принят</a></div>
<div class="inl-active"><a href="/truerecall">Перезвонили успешно</a></div>
<div class="inl"><a href="/falserecall">Перезвонили безуспешно</a></div>
</div>
<table>
<thead>
<tr>
<th>Номер клиента</th>
<th>Дата и время</th>
</tr>
</thead>
<tbody>
<tr>
{% for c in call %}
<!-- <td>{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}</td> -->
{% if c.mkt_phone == "83912051045": %}
<td>
<font color="#C30000">{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7],
c.client[7:11]) }}</font>
</td>
{% else %}
<td>{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}</td>
{% endif %}
<td>{{ c.dt }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>В работе</title>
</head>
<body style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;">
{% for c in call %}
<h3>{{ c.client }}</h3>
<table style="width: 500px; border: 1px; border-radius: 5px;">
<tr>
<td>Направление:</td>
<td> {{ c.direction }}</td>
</tr>
<tr>
<td>Продолжительность:</td>
<td> {{ c.answered_duration }}</td>
</tr>
<tr>
<td>Время события:</td>
<td>{{ c.time }}</td>
</tr>
<tr>
<td>Вызываемый номер:</td>
<td>{{ c.mkt_phone }}</td>
</tr>
</table>
<form action="/api/v1/work/" method="post">
<fieldset style="width: 500px;">
<legend>Результат</legend>
<div>
<input type="radio" name="recall" value="true" />
<label for="true">Дозвонились</label>
</div>
<div>
<input type="radio" name="recall" value="false" checked />
<label for="false">Не дозвонились</label>
</div>
<input type="hidden" name="uuid" value="{{ c.uuid }}" />
<p>
<div>
<input type="submit" value="Принять">
</div>
</fieldset>
</form>
{% endfor %}
</body>
</html>

View File

@ -79,7 +79,6 @@ def main():
# В этом месте описывается логика работы программы исходя основываясь на данных мобилона # В этом месте описывается логика работы программы исходя основываясь на данных мобилона
if res["direction"] == "incoming" and isBlack(res["from"]) == False: if res["direction"] == "incoming" and isBlack(res["from"]) == False:
# Подмена полей # Подмена полей
res["client"] = res.pop("from") res["client"] = res.pop("from")
res["mkt_phone"] = res.pop("to") res["mkt_phone"] = res.pop("to")
@ -87,27 +86,6 @@ def main():
coll.delete_many( coll.delete_many(
{"client": {'$regex': res["client"]}, "status": {"$in": ["NOT_ANSWERED", "RECALL_FALSE"]}}) {"client": {'$regex': res["client"]}, "status": {"$in": ["NOT_ANSWERED", "RECALL_FALSE"]}})
coll.insert_one(res) coll.insert_one(res)
if res["direction"] == "external":
res["client"] = res.pop("to")
res["operator"] = res.pop("from")
# Совершенно непонятный костыль, откуда берется загадка
res.pop("_id")
if res["has_record"] == True and res["answered_duration"] > min_recall_len_in_sec:
res["status"] = "RECALL_TRUE"
else:
res["status"] = "RECALL_FALSE"
t = coll.update_many({
"client": {'$regex': res["client"]},
"status": {'$in': ["NOT_ANSWERED", "RECALL_FALSE"]}
}, {'$set': res, '$inc': {"count_try": 1}})
coll.update_many({"count_try": {"$gt": 2}, "client": res["client"]}, {
"$set": {"status": "DELETED"}})
# ------------------------------- # -------------------------------
res.clear() res.clear()

144
dev/web/app.py Normal file
View File

@ -0,0 +1,144 @@
from urllib import request
from flask import Flask, jsonify, render_template, url_for, request, redirect
import json
import datetime
from pymongo import MongoClient
import requests
CONNECTION_STRING = "mongodb://mongodb:Cc03Wz5XX3iI3uY3@mongo"
db_connection = MongoClient(CONNECTION_STRING)
db_base = db_connection["phone-dev"]
coll = db_base["phone"]
bl = db_base["blacklist"]
rep = False
# coll_call = db_base["phone"]
# coll_history = db_base["history"]
app = Flask(__name__)
internal = {}
external = {}
State = ""
Findlimit = 100
@app.route("/")
def root():
return redirect("/notanswer")
ImportantNumber = ['839122051045']
@app.route("/answer")
def answer():
call = coll.find({"status": "ANSWERED"}).sort('time', -1).limit(Findlimit)
return render_template("answer.html", call=call) if rep == False else render_template("repair.html")
@app.route("/notanswer")
def notanswer():
call = coll.find({"status": "NOT_ANSWERED"}).sort(
'time', -1).limit(Findlimit)
return render_template("notanswer.html", call=call) if rep == False else render_template("repair.html")
@app.route("/truerecall")
def recallTrue():
call = coll.find({"status": "RECALL_TRUE"}).sort(
'time', -1).limit(Findlimit)
return render_template("truerecall.html", call=call) if rep == False else render_template("repair.html")
@app.route("/falserecall")
def rcallFalse():
call = coll.find({"status": "RECALL_FALSE"}).sort(
'time', -1).limit(Findlimit)
return render_template("falserecall.html", call=call) if rep == False else render_template("repair.html")
@app.route("/blacklist")
def blacklist():
call = bl.find().sort('_id')
return render_template("blacklist.html", call=call) if rep == False else render_template("repair.html")
@app.route("/test")
def ttt():
res = []
for p in request.environ:
try:
res.append(p + " = " + request.environ[p])
except:
pass
# #"<br>".join(request.environ)
return str(res)
@app.route("/work/<uuid>")
def work_uuid(uuid):
coll.update_one({"uuid": uuid}, {"$set": {"status": "INWORK"}})
call = coll.find({"uuid": uuid})
return render_template("work.html", call=call) if rep == False else render_template("repair.html")
# API
@app.route("/api/v1/call/set/", methods=["POST"])
def call_put():
# print(request.form)
if request.form["act"] == "delete":
coll.update_many({"uuid": request.form["uuid"], "status": "RECALL_FALSE"}, {
"$set": {"status": "DELETED"}})
return redirect("/falserecall")
@app.route("/api/v1/work/", methods=["POST"])
def work():
dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
coll.update_one({"uuid": request.form["uuid"]}, {
"$set": {"status": "RECALL_" + str(request.form["recall"]).upper(), "dt": dt}})
return redirect("/")
@app.route("/api/v1/blacklist/add/<number>", methods=["POST"])
def blacklist_put(number):
insdict = {"_id": number, "desc": datetime.datetime.now()}
bl.update_one({"_id": number}, {"$set": insdict}, True)
coll.update_many({"client": number, "status": {
"$in": ["RECALL_TRUE", "RECALL_FALSE", "NOT_ANSWERED"]}}, {"$set": {"status": "IGNORED"}})
return redirect("/blacklist")
@app.route("/api/v1/blacklist/delete/<number>", methods=["POST"])
def blacklist_delete(number):
bl.delete_many({"_id": number})
return redirect("/blacklist")
@app.route("/api/v1/blacklist/get/<number>")
def blacklist_get(number):
try:
return [i for i in bl.find({"_id": number})][0]
except:
return {}
@app.route("/api/v1/sync")
def sync():
j = []
for x in coll.find({"status": "NOT_ANSWERED"}):
t_req = "https://callinfo.services.mobilon.ru/api/call/info/1e86a98e026578eb5f6bf8c092c0c4a2/" + \
x["uuid"]
res: dict = json.loads(requests.get(t_req).content)
j.append(res)
coll.update_one({"uuid": x["uuid"]}, {"$set": res})
return j
if __name__ == "__main__":
app.debug = True
app.run(host="0.0.0.0", port=5000)

16
dev/web/dockerfile Normal file
View File

@ -0,0 +1,16 @@
FROM alpine
RUN apk update && apk upgrade && apk add python3 && apk add -U tzdata
WORKDIR /app
COPY requirements.txt requirements.txt
RUN python3 -m venv .venv
RUN /app/.venv/bin/pip3 install -r /app/requirements.txt
COPY app.py /app
COPY static /app/static
COPY templates /app/templates
EXPOSE 5000
CMD [".venv/bin/python3", "app.py"]

11
dev/web/requirements.txt Normal file
View File

@ -0,0 +1,11 @@
click==8.1.3
dnspython==2.3.0
Flask==2.2.3
importlib-metadata==6.2.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.2
pymongo==4.3.3
Werkzeug==2.2.3
zipp==3.15.0
requests==2.28.2

51
dev/web/static/main.css Normal file
View File

@ -0,0 +1,51 @@
table {
width: 100%;
margin-bottom: 20px;
border: 5px solid #fff;
border-top: 5px solid #fff;
border-bottom: 3px solid #fff;
border-collapse: collapse;
outline: 3px solid #ffd300;
font-size: 15px;
background: #fff !important;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
table th {
font-weight: bold;
padding: 7px;
background: #ffd300;
border: none;
text-align: left;
font-size: 15px;
border-top: 3px solid #fff;
border-bottom: 3px solid #ffd300;
}
table td {
padding: 7px;
border: none;
border-top: 3px solid #fff;
border-bottom: 3px solid #fff;
font-size: 15px;
}
table tbody tr:nth-child(even) {
background: #f8f8f8 !important;
}
a {
font-size: large;
font-family: Verdana, Geneva, Tahoma, sans-serif;
color: chocolate;
padding-right: 50px;
}
header {
height: 50px;
vertical-align: middle;
}
form {
height: 40px;
}

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Удаление документа</title>
</head>
<body>
<h2>Вы действительно хотите удалить номер: {{ id }}?</h2>
Причина удаления?
<form action="/web/call/delete/confirm" method="post">
<textarea name="reason"></textarea>
<input type="hidden" name="id" value="{{id}}">
<button type="submit">Удалить</button>
</form>
</body>
</html>

View File

@ -4,8 +4,8 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='main.css') }}"> <!-- <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='main.css') }}"> -->
<title>Перезвонили успешно</title> <title> Принятые вызовы</title>
</head> </head>
<style type="text/css" media="screen"> <style type="text/css" media="screen">
@ -63,16 +63,16 @@
.inl {display: inline;} .inl {display: inline;}
.inl-active { .inl-active {
display: inline; display: inline;
background-color: #FFD300; background-color: #FFD300;
} }
</style> </style>
<body> <body>
<div> <div>
<div class="inl"><a href="/answer">Входящий вызов принят</a></div> <div class="inl-active"><a href="/answer">Входящий вызов принят</a></div>
<div class="inl"><a href="/notanswer">Входящий вызов не принят</a></div> <div class="inl"><a href="/notanswer">Входящий вызов не принят</a></div>
<div class="inl-active"><a href="/truerecall">Перезвонили успешно</a></div> <div class="inl"><a href="/truerecall">Перезвонили успешно</a></div>
<div class="inl"><a href="/falserecall">Перезвонили безуспешно</a></div> <div class="inl"><a href="/falserecall">Перезвонили безуспешно</a></div>
</div> </div>
<!-- <div> <!-- <div>
@ -82,19 +82,18 @@
<input class="search_btn" type="submit" title="Найти"> <input class="search_btn" type="submit" title="Найти">
</form> </form>
</div> --> </div> -->
<table> <table>
<thead> <thead>
<tr> <tr>
<th>Номер клиента</th> <th>Номер клиента</th>
<th>Дата и время</th> <th>Дата и время</th>
<th>Продолжительность</th>
<th>Оператор</th>
<th>Запись разговора</th> <th>Запись разговора</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for c in call %}
<tr> <tr>
{% for c in call %}
<!-- <td>{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}</td> --> <!-- <td>{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}</td> -->
{% if c.mkt_phone == "83912051045": %} {% if c.mkt_phone == "83912051045": %}
<td> <td>
@ -106,8 +105,6 @@
{% endif %} {% endif %}
<td>{{ c.time }}</td> <td>{{ c.time }}</td>
<td>{{ c.answered_duration // 60 }}:{{ "{:02}".format(c.answered_duration % 60) }}</td>
<td>{{ c.operator }}</td>
<td><audio src="{{ c.record_url }}" type="audio/mp3" preload="none" controls>Запись</audio></td> <td><audio src="{{ c.record_url }}" type="audio/mp3" preload="none" controls>Запись</audio></td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='main.css') }}"> -->
<title>Черный список</title>
</head>
<style type="text/css" media="screen">
table {
width: 100%;
margin-bottom: 20px;
border: 5px solid #fff;
border-top: 5px solid #fff;
border-bottom: 3px solid #fff;
border-collapse: collapse;
outline: 3px solid #ffd300;
font-size: 15px;
background: #fff !important;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
table th {
font-weight: bold;
padding: 7px;
background: #ffd300;
border: none;
text-align: left;
font-size: 15px;
border-top: 3px solid #fff;
border-bottom: 3px solid #ffd300;
}
table td {
padding: 7px;
border: none;
border-top: 3px solid #fff;
border-bottom: 3px solid #fff;
font-size: 15px;
}
table tbody tr:nth-child(even) {
background: #f8f8f8 !important;
}
a {
font-size: large;
font-family: Verdana, Geneva, Tahoma, sans-serif;
color: chocolate;
padding-right: 50px;
}
header {
height: 50px;
vertical-align: middle;
}
form {
height: 40px;
}
</style>
<body>
<div>
<a href="/answer">Входящий вызов принят</a>
<a href="/notanswer">Входящий вызов не принят</a>
<a href="/truerecall">Перезвонили успешно</a>
<a href="/falserecall">Перезвонили безуспешно</a>
</div>
<table>
<thead>
<tr>
<th>Номер клиента</th>
<th>Комментарий</th>
<th>Действие</th>
</tr>
</thead>
<tbody>
{% for c in call %}
<tr>
<td>{{ c._id }}</td>
<td>{{ c.desc }}</td>
<td>
<form method="post" action="/api/v1/blacklist/delete/{{ c._id }}">
<input type="submit" value="Удалить" />
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,114 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='main.css') }}">
<title>Перезвонили безуспешно</title>
</head>
<style type="text/css" media="screen">
table {
width: 100%;
margin-bottom: 20px;
border: 5px solid #fff;
border-top: 5px solid #fff;
border-bottom: 3px solid #fff;
border-collapse: collapse;
outline: 3px solid #ffd300;
font-size: 15px;
background: #fff !important;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
table th {
font-weight: bold;
padding: 7px;
background: #ffd300;
border: none;
text-align: left;
font-size: 15px;
border-top: 3px solid #fff;
border-bottom: 3px solid #ffd300;
}
table td {
padding: 7px;
border: none;
border-top: 3px solid #fff;
border-bottom: 3px solid #fff;
font-size: 15px;
}
table tbody tr:nth-child(even) {
background: #f8f8f8 !important;
}
a {
font-size: large;
font-family: Verdana, Geneva, Tahoma, sans-serif;
color: #7A1E99;
padding-right: 50px;
}
header {
height: 50px;
vertical-align: middle;
}
form {
height: 40px;
}
.inl {display: inline;}
.inl-active {
display: inline;
background-color: #FFD300;
}
</style>
<body>
<div>
<div class="inl"><a href="/answer">Входящий вызов принят</a></div>
<div class="inl"><a href="/notanswer">Входящий вызов не принят</a></div>
<div class="inl"><a href="/truerecall">Перезвонили успешно</a></div>
<div class="inl-active"><a href="/falserecall">Перезвонили безуспешно</a></div>
</div>
<table>
<thead>
<tr>
<th>Номер клиента</th>
<th>Дата и время</th>
<th>Действие</th>
</tr>
</thead>
<tbody>
{% for c in call %}
<tr>
{% if c.mkt_phone == "83912051045": %}
<td>
<font color="#C30000">{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7],
c.client[7:11]) }}</font>
</td>
{% else %}
<td>{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}</td>
{% endif %}
<td>{{ c.dt }}</td>
<td style="vertical-align: middle;">
<div>
<form action="/api/v1/call/set/" method="post" style="border: 0;">
<input type="hidden" name="uuid" value="{{ c.uuid }}" />
<input type="hidden" name="act" value="delete" />
<input type="submit" value="Удалить" style="background-color: firebrick; color: #f8f8f8;" />
</form>
</div>
</td>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,130 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='main.css') }}"> -->
<!-- <link rel="stylesheet" type="text/css" href="http://dev-call.mkt.local/static/main.css"> -->
<title>Непринятые</title>
</head>
<style type="text/css" media="screen">
table {
width: 100%;
margin-bottom: 20px;
border: 5px solid #fff;
border-top: 5px solid #fff;
border-bottom: 3px solid #fff;
border-collapse: collapse;
outline: 3px solid #ffd300;
font-size: 15px;
background: #fff !important;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
table th {
font-weight: bold;
padding: 7px;
background: #ffd300;
border: none;
text-align: left;
font-size: 15px;
border-top: 3px solid #fff;
border-bottom: 3px solid #ffd300;
}
table td {
padding: 7px;
border: none;
border-top: 3px solid #fff;
border-bottom: 3px solid #fff;
font-size: 15px;
}
table tbody tr:nth-child(even) {
background: #f8f8f8 !important;
}
a {
font-size: large;
font-family: Verdana, Geneva, Tahoma, sans-serif;
color: #7A1E99;
padding-right: 50px;
}
header {
height: 50px;
vertical-align: middle;
}
form {
height: 40px;
}
.inl {
display: inline;
}
.inl-active {
display: inline;
background-color: #FFD300;
}
</style>
<body>
<div>
<div class="inl"><a href="/answer">Входящий вызов принят</a></div>
<div class="inl-active"><a href="/notanswer">Входящий вызов не принят</a></div>
<div class="inl"><a href="/truerecall">Перезвонили успешно</a></div>
<div class="inl"><a href="/falserecall">Перезвонили безуспешно</a></div>
</div>
<div>
</div>
<table>
<thead>
<tr>
<th>Номер клиента</th>
<th>Дата и время</th>
<th>Продолжительность</th>
<th>Действие</th>
</tr>
</thead>
<tbody>
{% for c in call %}
<tr>
{% if c.mkt_phone == "83912051045": %}
<td>
<font color="#C30000">
<a href="/work/{{ c.uuid }}">
{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}
</a>
</font>
</td>
{% else %}
<td>
<a href="/work/{{ c.uuid }}">
{{ "%s %s %s %s" |format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}
</a>
</td>
{% endif %}
<td>{{ c.time }} {{ c.important }}</td>
<td>{{ c.answered_duration // 60 }}:{{ "{:02}".format(c.answered_duration % 60) }}</td>
<td>
<form action="/api/v1/blacklist/add/{{ c.client }}" method="post" style="border: 0;" />
<input type="submit" value="В черный список" style="background-color: dimgray; color: #fff;" />
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Ведутся работы, скоро все заработает</h1>
</body>
</html>

View File

@ -0,0 +1,104 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='main.css') }}">
<title>Перезвонили успешно</title>
</head>
<style type="text/css" media="screen">
table {
width: 100%;
margin-bottom: 20px;
border: 5px solid #fff;
border-top: 5px solid #fff;
border-bottom: 3px solid #fff;
border-collapse: collapse;
outline: 3px solid #ffd300;
font-size: 15px;
background: #fff !important;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
table th {
font-weight: bold;
padding: 7px;
background: #ffd300;
border: none;
text-align: left;
font-size: 15px;
border-top: 3px solid #fff;
border-bottom: 3px solid #ffd300;
}
table td {
padding: 7px;
border: none;
border-top: 3px solid #fff;
border-bottom: 3px solid #fff;
font-size: 15px;
}
table tbody tr:nth-child(even) {
background: #f8f8f8 !important;
}
a {
font-size: large;
font-family: Verdana, Geneva, Tahoma, sans-serif;
color: #7A1E99;
padding-right: 50px;
}
header {
height: 50px;
vertical-align: middle;
}
form {
height: 40px;
}
.inl {display: inline;}
.inl-active {
display: inline;
background-color: #FFD300;
}
</style>
<body>
<div>
<div class="inl"><a href="/answer">Входящий вызов принят</a></div>
<div class="inl"><a href="/notanswer">Входящий вызов не принят</a></div>
<div class="inl-active"><a href="/truerecall">Перезвонили успешно</a></div>
<div class="inl"><a href="/falserecall">Перезвонили безуспешно</a></div>
</div>
<table>
<thead>
<tr>
<th>Номер клиента</th>
<th>Дата и время</th>
</tr>
</thead>
<tbody>
<tr>
{% for c in call %}
<!-- <td>{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}</td> -->
{% if c.mkt_phone == "83912051045": %}
<td>
<font color="#C30000">{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7],
c.client[7:11]) }}</font>
</td>
{% else %}
<td>{{ "%s %s %s %s"|format(c.client[0:1], c.client[1:4], c.client[4:7], c.client[7:11]) }}</td>
{% endif %}
<td>{{ c.dt }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>В работе</title>
</head>
<body style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;">
{% for c in call %}
<h3>{{ c.client }}</h3>
<table style="width: 500px; border: 1px; border-radius: 5px;">
<tr>
<td>Направление:</td>
<td> {{ c.direction }}</td>
</tr>
<tr>
<td>Продолжительность:</td>
<td> {{ c.answered_duration }}</td>
</tr>
<tr>
<td>Время события:</td>
<td>{{ c.time }}</td>
</tr>
<tr>
<td>Вызываемый номер:</td>
<td>{{ c.mkt_phone }}</td>
</tr>
</table>
<form action="/api/v1/work/" method="post">
<fieldset style="width: 500px;">
<legend>Результат</legend>
<div>
<input type="radio" name="recall" value="true" />
<label for="true">Дозвонились</label>
</div>
<div>
<input type="radio" name="recall" value="false" checked />
<label for="false">Не дозвонились</label>
</div>
<input type="hidden" name="uuid" value="{{ c.uuid }}" />
<p>
<div>
<input type="submit" value="Принять">
</div>
</fieldset>
</form>
{% endfor %}
</body>
</html>

107
dev/worker/app.py Normal file
View File

@ -0,0 +1,107 @@
import pika
import sys
import os
import json
import datetime
from pymongo import MongoClient
import time
from phone import phone
import requests
db_connection = MongoClient("mongodb://mongodb:Cc03Wz5XX3iI3uY3@mongo")
db_base = db_connection["phone-dev"]
coll = db_base["phone"]
coll_all = db_base["phone-all"]
err = db_base["err"]
blacklist = db_base["blacklist"]
phoneDebug = db_base["phone-debug"]
coll_userkey = db_base['userkey']
mkt_phones = ['83912051046', '83912051045']
mobilon_wait = 5 # Время ожидания необходимо чтобы на стороне мобилона все улеглось
min_recall_len_in_sec = 8
def isBlack(number: str) -> bool:
return True if blacklist.count_documents({"_id": number}) > 0 else False
# Stats:
# 0 - ответили
# 1 - не приняли
# 2 - перезвонили успешно
# 4 - Перезвонили неуспешно
# LOG
# 0 - выходящий вызов закончен
# 1 - Вызов не принят
# 2 - Перезвонили и дозвонились
def main():
connection = pika.BlockingConnection(pika.ConnectionParameters(
'rabbitmq', 5672, 'mkt', pika.PlainCredentials('rabbit', 'mrl2X0jwnYuCCiKFTshG7WKyOAhfDo')))
channel = connection.channel()
channel.queue_declare(queue='dev-incoming')
def callback(ch, method, properties, body: bytearray):
# Парсим строку
ph = phone(body)
# Определяем тип соединения
# Если входящий
print(ph.ConvertToJSON())
phoneDebug.insert_one(ph.ConvertToJSON())
if ph.GetState() == "START":
ph.addStart()
if ph.GetState() == "END":
ph.addEnd()
if ph.GetState() == "HANGUP" and ph.isCanClose() == 1:
# Ждем
time.sleep(mobilon_wait)
t_req = "https://callinfo.services.mobilon.ru/api/call/info/1e86a98e026578eb5f6bf8c092c0c4a2/" + ph.GetUUID()
try:
res: dict = json.loads(requests.get(t_req).content)
except:
print("Get data from Mobilon", t_req)
try:
coll_all.insert_one(res)
except:
print("coll_all:", res)
# В этом месте описывается логика работы программы исходя основываясь на данных мобилона
if res["direction"] == "incoming" and isBlack(res["from"]) == False:
# Подмена полей
res["client"] = res.pop("from")
res["mkt_phone"] = res.pop("to")
# 2. Удаляем пропущенные если есть
coll.delete_many(
{"client": {'$regex': res["client"]}, "status": {"$in": ["NOT_ANSWERED", "RECALL_FALSE"]}})
coll.insert_one(res)
# -------------------------------
res.clear()
channel.basic_consume(
queue='incoming-dev', on_message_callback=callback, auto_ack=True)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('Interrupted')
try:
sys.exit(0)
except SystemExit:
os._exit(0)

View File

@ -5,10 +5,9 @@ RUN apk update && apk upgrade && apk add python3 && apk add -U tzdata
WORKDIR /app WORKDIR /app
COPY requirements.txt requirements.txt COPY requirements.txt requirements.txt
ADD *.py /app
RUN python3 -m venv .venv RUN python3 -m venv .venv
RUN /app/.venv/bin/pip3 install -r /app/requirements.txt RUN /app/.venv/bin/pip3 install -r /app/requirements.txt
ADD *.py /app
EXPOSE 5000 EXPOSE 5000
CMD [".venv/bin/python3", "app.py"] CMD [".venv/bin/python3", "app.py"]

60
dev/worker/phone.py Normal file
View File

@ -0,0 +1,60 @@
import json
import redis
r = redis.Redis(host="redis")
class phone:
def __init__(self, message: bytearray):
self.msg = message
self.dict = self.ConvertToJSON()
def ConvertToJSON(self):
try:
return json.loads(str(self.msg.decode('utf-8')).replace("\'", "\""))
except:
return {}
# def GetDirection(self) -> str:
# return self.dict["direction"]
def GetUUID(self) -> str:
return self.dict["uuid"]
# def GetClient(self) -> str:
# return self.dict["from"] if self.GetDirection() == "incoming" else self.dict["to"]
# def GetOperator(self) -> str:
# return self.dict["to"] if self.GetDirection() == "incoming" else self.dict["from"]
# def GetTimestamp(self) -> int:
# """Return int timestamp"""
# return self.dict["time"]
def GetState(self) -> str:
return self.dict["state"]
# def isIncoming(self) -> bool:
# """True Если входящий, иначе False"""
# return True if self.GetDirection() == "incoming" else False
# def isExternal(self) -> bool:
# """True если исходящий, иначе False"""
# return True if self.GetDirection() == "external" else False
def isCanClose(self) -> int:
try:
return int(r.hget(self.GetUUID(), "canClose"))
except:
return 0
def addStart(self):
r.hset(self.GetUUID(), mapping={
"canClose": "0"
})
def addEnd(self):
r.hset(self.GetUUID(), mapping={
"canClose": "1"
})

View File

@ -0,0 +1,18 @@
async-timeout==4.0.3
click==8.1.3
dnspython==2.3.0
Flask==2.2.3
importlib-metadata==6.2.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.2
pika==1.3.1
pymongo==4.3.3
certifi==2022.12.7
charset-normalizer==3.1.0
idna==3.4
requests==2.28.2
urllib3==1.26.15
redis==5.0.1
Werkzeug==2.2.3
zipp==3.15.0

View File

@ -96,6 +96,27 @@ services:
- phone - phone
ports: ports:
- 6001:6001 - 6001:6001
dev-worker:
build: ./dev/worker
restart: always
environment:
- TZ=Asia/Krasnoyarsk
depends_on:
- mongo
networks:
- phone
dev-web:
build: ./dev/web
restart: always
environment:
- TZ=Asia/Krasnoyarsk
depends_on:
- mongo
networks:
- phone
ports:
- 7001:5000
networks: networks:
phone: phone:

View File

@ -1,43 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='main.css') }}">
<title>Lost Calls</title>
</head>
<header>
<a href="/web/call/status/0">Входящий вызов принят</a>
<a href="/web/call/status/1">Входящий вызов не принят</a>
<a href="/web/call/status/2">Перезвонили</a>
</header>
<table>
<tr>
<td>Номер клиента</td>
<!-- <td>Номер оператора</td> -->
<td>Дата время</td>
<td>Ссылка на запись</td>
</tr>
<body>
{% for entry in call %}
<tr>
<!-- <td>{{ entry.client }}</td> -->
<td><a href="tel:{{ entry.client }}">{{ "%s %s %s %s"|format(entry.client[0:1], entry.client[1:4], entry.client[4:7], entry.client[7:11]) }}</a></td>
<!-- <td>{{ entry.Operator }}</td> -->
<td>{{ entry.time }}</td>
<td>
{% if entry.recordUrl|length > 1 %}
<audio src="{{ entry.recordUrl }}" type="audio/mp3" preload="none" controls>Запись</audio>
{% endif %}
</td>
</tr>
{% endfor %}
</body>
</table>
</html>

View File

@ -1,79 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='main.css') }}">
<title>Lost Calls</title>
</head>
<header>
<a href="/web/call/status/0">Входящий вызов принят</a>
<a href="/web/call/status/1">Входящий вызов не принят</a>
<<<<<<< HEAD
<a href="/web/call/status/2">Перезвонили успешно</a>
<a href="/web/call/status/4">Перезвонили безуспешно</a>
<p>
<form name="search" action="/web/call/find/" method="get" class="search">
<label class="search_label">Поиск</label>
<input class="search_text" type="text" name="client">
<input class="search_btn" type="submit" title="Найти">
</form>
</p>
=======
<a href="/web/call/status/2">Перезвонили</a>
>>>>>>> parent of c52dc73 (Добавил поиск)
</header>
<table>
<tr>
<td>Номер клиента</td>
<!-- <td>Номер оператора</td> -->
<td>Дата время</td>
<td>Ссылка на запись</td>
</tr>
<body>
{% for entry in call %}
<tr>
<!-- <td>{{ entry.client }}</td> -->
{% if entry.important == True %}
<td>
<font color="#C30000">{{ "%s %s %s %s"|format(entry.client[0:1], entry.client[1:4], entry.client[4:7],
entry.client[7:11]) }}</font>
</td>
{% else %}
<td>{{ "%s %s %s %s"|format(entry.client[0:1], entry.client[1:4], entry.client[4:7], entry.client[7:11]) }}
</td>
{% endif %}
<!-- <td>{{ entry.Operator }}</td> -->
<td>{{ entry.time }}</td>
<td>
<<<<<<< HEAD
{% if entry.status == 0 %}
Вызов принят
{% elif entry.status == 1 %}
Вызов не принят
{% elif entry.status == 2 %}
Перезвонили
{% elif entry.status == 2 %}
Абонент не взял трубку
{% elif entry.status == 9 %}
Абонент заблокирован
{% endif %}
</td>
<td>
=======
>>>>>>> parent of c52dc73 (Добавил поиск)
{% if entry.recordUrl|length > 1 %}
<audio src="{{ entry.recordUrl }}" type="audio/mp3" preload="none" controls>Запись</audio>
{% endif %}
</td>
</tr>
{% endfor %}
</body>
</table>
</html>

View File

@ -64,6 +64,7 @@ def blacklist():
call = bl.find().sort('_id') call = bl.find().sort('_id')
return render_template("blacklist.html", call=call) if rep == False else render_template("repair.html") return render_template("blacklist.html", call=call) if rep == False else render_template("repair.html")
@app.route("/test") @app.route("/test")
def ttt(): def ttt():
res = [] res = []
@ -75,6 +76,7 @@ def ttt():
# #"<br>".join(request.environ) # #"<br>".join(request.environ)
return str(res) return str(res)
@app.route("/work/<uuid>") @app.route("/work/<uuid>")
def work_uuid(uuid): def work_uuid(uuid):
coll.update_one({"uuid": uuid}, {"$set": {"status": "INWORK"}}) coll.update_one({"uuid": uuid}, {"$set": {"status": "INWORK"}})
@ -96,9 +98,11 @@ def call_put():
@app.route("/api/v1/work/", methods=["POST"]) @app.route("/api/v1/work/", methods=["POST"])
def work(): def work():
dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
coll.update_one({"uuid": request.form["uuid"]}, {"$set": {"status": "RECALL_" + str(request.form["recall"]).upper(), "dt": dt}}) coll.update_one({"uuid": request.form["uuid"]}, {
"$set": {"status": "RECALL_" + str(request.form["recall"]).upper(), "dt": dt}})
return redirect("/") return redirect("/")
@app.route("/api/v1/blacklist/add/<number>", methods=["POST"]) @app.route("/api/v1/blacklist/add/<number>", methods=["POST"])
def blacklist_put(number): def blacklist_put(number):
insdict = {"_id": number, "desc": datetime.datetime.now()} insdict = {"_id": number, "desc": datetime.datetime.now()}

View File

@ -1,44 +0,0 @@
import pika
import sys
import os
import json
import datetime
import re
import config
from pymongo import MongoClient
from msg import msg
import requests
import time
def main():
connection = pika.BlockingConnection(pika.ConnectionParameters(
"192.168.0.20", 5672, "mkt", pika.PlainCredentials(
"rabbit", "mrl2X0jwnYuCCiKFTshG7WKyOAhfDo")
))
channel = connection.channel()
def callback(ch, method, properties, body: bytearray):
srcJson = json.loads(str(body.decode('utf-8')).replace("\'", "\""))
# if srcJson['state'] == 'HANGUP' and srcJson['direction'] == 'incoming' and srcJson['from'] == '89135853246':
try:
if srcJson['callstatus'] != 'ANSWER':
print(srcJson)
except:
pass
channel.basic_consume(
queue='incoming-dev', on_message_callback=callback, auto_ack=False)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('Interrupted')
try:
sys.exit(0)
except SystemExit:
os._exit(0)

View File

@ -1,16 +0,0 @@
IMPORTANT_LINE = ['83912051045']
IGNORE_LIST = ['83912051045',
'83912051046',
'83919865589',
'83919865589',
'84950213944',
'84951183750',
'84951252791',
'89919237009',
'89919241441',
'89919398228',
'89919500798',
'89919505445',
'89919863883']

View File

@ -1,94 +0,0 @@
import pika
import sys
import os
import json
import datetime
import re
import config
from pymongo import MongoClient
from msg import msg
import requests
import time
CONNECTION_STRING = "mongodb://mongodb:Cc03Wz5XX3iI3uY3@192.168.0.20"
db_connection = MongoClient(CONNECTION_STRING)
db_base = db_connection["phone"]
coll_call = db_base["phone_dev"]
from_api = db_base["from_api"]
def main():
connection = pika.BlockingConnection(pika.ConnectionParameters(
"192.168.0.20", 5672, "mkt", pika.PlainCredentials(
"rabbit", "mrl2X0jwnYuCCiKFTshG7WKyOAhfDo")
))
channel = connection.channel()
def callback(ch, method, properties, body: bytearray):
m = msg(body)
# Разбираем входящие звонки
if m.isIncoming():
# Если статус START
if m.getState() == "START":
insert_value = {
"uuid": m.getUUID(),
"status": -1,
"canClose": 0
}
coll_call.update_one(
filter={"client": m.getClient(), "status": -1},
update={"$set": insert_value},
upsert=True
)
#print("НАЧАТ:", m.dict)
# Если Статус END
if m.getState() == "END":
coll_call.update_one(
filter={"uuid": m.getUUID()},
update={"$set": {"canClose": 1}}
)
#print("ЗАКОНЧЕН:", m.dict)
time.sleep(5)
resp = requests.get("https://callinfo.services.mobilon.ru/api/call/info/1e86a98e026578eb5f6bf8c092c0c4a2/" + m.getUUID())
j = json.loads(resp.content.decode('utf-8'))
d = dict(j)
from_api.insert_one(d)
# Если статус HANGUP
if m.getState() == "HANGUP":
if m.isAnswered():
insert_value = {
"status": 0,
"duration": m.getDuration(),
"recordUrl": m.getRecordUrl()
}
else:
insert_value = {
"status": 1
}
coll_call.update_one(
filter={"uuid": m.getUUID(), "canClose": 1},
update={"$set": insert_value}
)
#print("Положена трубка:", m.dict)
channel.basic_consume(
queue='test', on_message_callback=callback, auto_ack=True)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('Interrupted')
try:
sys.exit(0)
except SystemExit:
os._exit(0)

View File

@ -1,68 +0,0 @@
import os
import json
import datetime
import re
import config
class msg:
def __init__(self, body):
self.body: bytearray = body
self.decode: str = self.body.decode('utf-8')
self.json: json = json.loads(self.decode.replace("\'", "\""))
self.dict: dict = dict(self.json)
def getDirection(self):
try:
return self.dict["direction"]
except:
pass
def isIncoming(self) -> bool:
return True if self.dict["direction"] == "incoming" else False
def isExternal(self) -> bool:
return not self.isIncoming()
def getState(self) -> str:
try:
return self.dict["state"]
except:
pass
def getClient(self) -> str:
return self.dict["from"] if self.isIncoming() else self.dict["to"]
def getTime(self) -> str:
try:
return datetime.datetime.fromtimestamp(self.dict["time"]).strftime('%Y-%m-%d %H:%M:%S')
except:
return None
def getStatus(self) -> int:
pass
def getRecordUrl(self) -> str:
return self.dict["recordUrl"]
def getDuration(self) -> int:
return self.dict["duration"]
def getUUID(self) -> str:
try:
return self.dict["uuid"]
except:
pass
def isAnswered(self) -> bool:
try:
self.dict["callstatus"]
return True
except:
return False
def isImportant(self):
try:
return True if self.getState() == "START" and self.isIncoming() and self.dict["to"] in config.IMPORTANT_LINE else False
except:
pass

View File

@ -1,8 +0,0 @@
dnspython==2.3.0
pika==1.3.1
pymongo==4.3.3
certifi==2022.12.7
charset-normalizer==3.1.0
idna==3.4
requests==2.28.2
urllib3==1.26.15

View File

@ -9,7 +9,7 @@ from phone import phone
import requests import requests
db_connection = MongoClient("mongodb://mongodb:Cc03Wz5XX3iI3uY3@mongo") db_connection = MongoClient("mongodb://mongodb:Cc03Wz5XX3iI3uY3@mongo")
db_base = db_connection["phone-dev"] db_base = db_connection["dev-phone"]
coll = db_base["phone"] coll = db_base["phone"]
coll_all = db_base["phone-all"] coll_all = db_base["phone-all"]
err = db_base["err"] err = db_base["err"]