Compare commits
No commits in common. "e03a34c47a6ed64a6ee78167c8e84a3866d00ea4" and "c52dc734f659855efd5747495ff5240166c667b9" have entirely different histories.
e03a34c47a
...
c52dc734f6
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1 @@
|
|||||||
**/.venv
|
**/.venv
|
||||||
**/venv
|
|
||||||
**/.vscode
|
|
||||||
|
@ -15,12 +15,6 @@ services:
|
|||||||
- phone
|
- phone
|
||||||
volumes:
|
volumes:
|
||||||
- rabbitmq:/var/lib/rabbitmq
|
- rabbitmq:/var/lib/rabbitmq
|
||||||
redis:
|
|
||||||
image: redis/redis-stack:latest
|
|
||||||
ports:
|
|
||||||
- 8001:8001
|
|
||||||
networks:
|
|
||||||
- phone
|
|
||||||
reciever:
|
reciever:
|
||||||
build: ./reciever
|
build: ./reciever
|
||||||
restart: always
|
restart: always
|
||||||
@ -76,27 +70,6 @@ services:
|
|||||||
- phone
|
- phone
|
||||||
ports:
|
ports:
|
||||||
- 5002:5002
|
- 5002:5002
|
||||||
worker-dev:
|
|
||||||
build: ./worker-dev
|
|
||||||
restart: always
|
|
||||||
environment:
|
|
||||||
- TZ=Asia/Krasnoyarsk
|
|
||||||
depends_on:
|
|
||||||
- mongo
|
|
||||||
networks:
|
|
||||||
- phone
|
|
||||||
web-dev:
|
|
||||||
build: ./web-dev
|
|
||||||
restart: always
|
|
||||||
environment:
|
|
||||||
- TZ=Asia/Krasnoyarsk
|
|
||||||
depends_on:
|
|
||||||
- mongo
|
|
||||||
networks:
|
|
||||||
- phone
|
|
||||||
ports:
|
|
||||||
- 6001:6001
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
phone:
|
phone:
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
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")
|
|
||||||
|
|
||||||
# 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/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=6001)
|
|
@ -1,16 +0,0 @@
|
|||||||
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 5001
|
|
||||||
|
|
||||||
CMD [".venv/bin/python3", "app.py"]
|
|
@ -1,11 +0,0 @@
|
|||||||
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
|
|
@ -1,51 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
@ -1,22 +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">
|
|
||||||
<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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -1,115 +0,0 @@
|
|||||||
<!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-active"><a href="/answer">Входящий вызов принят</a></div>
|
|
||||||
<div class="inl"><a href="/notanswer">Входящий вызов не принят</a></div>
|
|
||||||
<div class="inl"><a href="/truerecall">Перезвонили успешно</a></div>
|
|
||||||
<div class="inl"><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>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Номер клиента</th>
|
|
||||||
<th>Дата и время</th>
|
|
||||||
<th>Запись разговора</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for c in call %}
|
|
||||||
<tr>
|
|
||||||
<!-- <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.time }}</td>
|
|
||||||
<td><audio src="{{ c.record_url }}" type="audio/mp3" preload="none" controls>Запись</audio></td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,104 +0,0 @@
|
|||||||
<!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>
|
|
||||||
<!-- <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>
|
|
||||||
<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>
|
|
@ -1,134 +0,0 @@
|
|||||||
<!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>
|
|
||||||
<!-- <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>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Номер клиента</th>
|
|
||||||
<th>Кол-во попыток</th>
|
|
||||||
<th>Дата и время</th>
|
|
||||||
<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">{{ "%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.count_try }}</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;">
|
|
||||||
<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>
|
|
@ -1,125 +0,0 @@
|
|||||||
<!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>
|
|
||||||
|
|
||||||
<!-- <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>
|
|
||||||
<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">{{ "%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.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>
|
|
@ -1,14 +0,0 @@
|
|||||||
<!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>
|
|
@ -1,118 +0,0 @@
|
|||||||
<!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>
|
|
||||||
<!-- <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>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Номер клиента</th>
|
|
||||||
<th>Дата и время</th>
|
|
||||||
<th>Продолжительность</th>
|
|
||||||
<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.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>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
140
web-dev/app.py
140
web-dev/app.py
@ -1,140 +0,0 @@
|
|||||||
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=6001)
|
|
@ -1,16 +0,0 @@
|
|||||||
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 5001
|
|
||||||
|
|
||||||
CMD [".venv/bin/python3", "app.py"]
|
|
@ -1,11 +0,0 @@
|
|||||||
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
|
|
@ -1,51 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
@ -1,22 +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">
|
|
||||||
<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>
|
|
@ -1,115 +0,0 @@
|
|||||||
<!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-active"><a href="/answer">Входящий вызов принят</a></div>
|
|
||||||
<div class="inl"><a href="/notanswer">Входящий вызов не принят</a></div>
|
|
||||||
<div class="inl"><a href="/truerecall">Перезвонили успешно</a></div>
|
|
||||||
<div class="inl"><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>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Номер клиента</th>
|
|
||||||
<th>Дата и время</th>
|
|
||||||
<th>Запись разговора</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for c in call %}
|
|
||||||
<tr>
|
|
||||||
<!-- <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.time }}</td>
|
|
||||||
<td><audio src="{{ c.record_url }}" type="audio/mp3" preload="none" controls>Запись</audio></td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,97 +0,0 @@
|
|||||||
<!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>
|
|
@ -1,114 +0,0 @@
|
|||||||
<!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>
|
|
@ -1,130 +0,0 @@
|
|||||||
<!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>
|
|
@ -1,14 +0,0 @@
|
|||||||
<!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>
|
|
@ -1,104 +0,0 @@
|
|||||||
<!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>
|
|
@ -1,55 +0,0 @@
|
|||||||
<!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>
|
|
22
web/app.py
22
web/app.py
@ -16,7 +16,7 @@ app = Flask(__name__)
|
|||||||
internal = {}
|
internal = {}
|
||||||
external = {}
|
external = {}
|
||||||
State = ""
|
State = ""
|
||||||
findLimit = 200
|
findLimit = 1000
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def root():
|
def root():
|
||||||
@ -29,32 +29,15 @@ IgnoreList = ['83919865589', '83912051046', '83912051045', '84950213944', '84951
|
|||||||
|
|
||||||
@app.route("/web/call/")
|
@app.route("/web/call/")
|
||||||
def WebCall():
|
def WebCall():
|
||||||
|
call = coll_call.find().sort('time', -1)
|
||||||
call = coll_call.find().limit(findLimit).sort('time', -1)
|
|
||||||
return render_template("WebCall.html", call=call)
|
return render_template("WebCall.html", call=call)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/web/call/test/")
|
|
||||||
def GetTest():
|
|
||||||
call = coll_call.find({'client': {'$nin': IgnoreList}}).limit(findLimit).sort('time', -1)
|
|
||||||
return render_template("TestCall.html", call=call)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/web/call/test/<id>")
|
|
||||||
def GetTestId(id):
|
|
||||||
call = coll_call.find(
|
|
||||||
{'client': {'$nin': IgnoreList}, 'status': int(id)}).sort('time', -1)
|
|
||||||
return render_template("TestCall.html", call=call)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/web/call/status/<id>")
|
@app.route("/web/call/status/<id>")
|
||||||
def WebCallStatus(id):
|
def WebCallStatus(id):
|
||||||
call = coll_call.find({"status": int(id)}).sort('time', -1)
|
|
||||||
call = coll_call.find(
|
call = coll_call.find(
|
||||||
{'client': {'$nin': IgnoreList}, 'status': int(id)}).limit(findLimit).sort('time', -1)
|
{'client': {'$nin': IgnoreList}, 'status': int(id)}).limit(findLimit).sort('time', -1)
|
||||||
return render_template("WebCall.html", call=call)
|
return render_template("WebCall.html", call=call)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/web/call/find/", methods=["GET"])
|
@app.route("/web/call/find/", methods=["GET"])
|
||||||
def WebCallFind():
|
def WebCallFind():
|
||||||
try:
|
try:
|
||||||
@ -64,7 +47,6 @@ def WebCallFind():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return(str(e))
|
return(str(e))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.debug = True
|
app.debug = True
|
||||||
app.run(host="0.0.0.0", port=5001)
|
app.run(host="0.0.0.0", port=5001)
|
||||||
|
@ -42,6 +42,29 @@ a {
|
|||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
height: 50px;
|
height: 80px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search_label {
|
||||||
|
color: chocolate;
|
||||||
|
font-family: Verdana, Geneva, Tahoma, sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search_text {
|
||||||
|
color: chocolate;
|
||||||
|
font-family: Verdana, Geneva, Tahoma, sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search_btn {
|
||||||
|
color: chocolate;
|
||||||
|
font-family: Verdana, Geneva, Tahoma, sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
@ -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>
|
|
@ -11,22 +11,20 @@
|
|||||||
<header>
|
<header>
|
||||||
<a href="/web/call/status/0">Входящий вызов принят</a>
|
<a href="/web/call/status/0">Входящий вызов принят</a>
|
||||||
<a href="/web/call/status/1">Входящий вызов не принят</a>
|
<a href="/web/call/status/1">Входящий вызов не принят</a>
|
||||||
<a href="/web/call/status/2">Перезвонили успешно</a>
|
<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>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Номер клиента</td>
|
<td>Номер клиента</td>
|
||||||
<td>Дата время</td>
|
<td>Дата время</td>
|
||||||
|
<td>Статус звонка</td>
|
||||||
<td>Ссылка на запись</td>
|
<td>Ссылка на запись</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@ -35,27 +33,21 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<!-- <td>{{ entry.client }}</td> -->
|
<!-- <td>{{ entry.client }}</td> -->
|
||||||
{% if entry.important == True %}
|
{% if entry.important == True %}
|
||||||
<td>
|
<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>
|
||||||
<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 %}
|
{% else %}
|
||||||
<td>{{ "%s %s %s %s"|format(entry.client[0:1], entry.client[1:4], entry.client[4:7], entry.client[7:11]) }}
|
<td >{{ "%s %s %s %s"|format(entry.client[0:1], entry.client[1:4], entry.client[4:7], entry.client[7:11]) }}</td>
|
||||||
</td>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<!-- <td>{{ entry.Operator }}</td> -->
|
<!-- <td>{{ entry.Operator }}</td> -->
|
||||||
<td>{{ entry.time }}</td>
|
<td>{{ entry.time }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if entry.status == 0 %}
|
{% if entry.status == 0 %}
|
||||||
Вызов принят
|
Вызов принят
|
||||||
{% elif entry.status == 1 %}
|
{% elif entry.status == 1 %}
|
||||||
Вызов не принят
|
Вызов не принят
|
||||||
{% elif entry.status == 2 %}
|
{% elif entry.status == 2 %}
|
||||||
Перезвонили
|
Перезвонили
|
||||||
{% elif entry.status == 2 %}
|
|
||||||
Абонент не взял трубку
|
|
||||||
{% elif entry.status == 9 %}
|
{% elif entry.status == 9 %}
|
||||||
Абонент заблокирован
|
Абонент заблокирован
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -12,21 +12,34 @@
|
|||||||
<a href="/web/call/status/0">Входящий вызов принят</a>
|
<a href="/web/call/status/0">Входящий вызов принят</a>
|
||||||
<a href="/web/call/status/1">Входящий вызов не принят</a>
|
<a href="/web/call/status/1">Входящий вызов не принят</a>
|
||||||
<a href="/web/call/status/2">Перезвонили</a>
|
<a href="/web/call/status/2">Перезвонили</a>
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<form name="search" action="/web/call/find/" method="get">
|
||||||
|
<label>Поиск</label>
|
||||||
|
<input type="text" name="client" value="">
|
||||||
|
<input type="submit" title="Найти">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Номер клиента</td>
|
<td>Номер клиента</td>
|
||||||
<!-- <td>Номер оператора</td> -->
|
<!-- <td>Номер оператора</td> -->
|
||||||
<td>Дата время</td>
|
<td>Дата время события</td>
|
||||||
<td>Ссылка на запись</td>
|
<td>Ссылка на запись</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
{% for entry in call %}
|
{% for entry in call %}
|
||||||
<tr>
|
<tr>
|
||||||
<!-- <td>{{ entry.client }}</td> -->
|
<!-- <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>
|
{% 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.Operator }}</td> -->
|
||||||
<td>{{ entry.time }}</td>
|
<td>{{ entry.time }}</td>
|
||||||
<td>
|
<td>
|
@ -22,7 +22,6 @@
|
|||||||
<!-- <td>Номер оператора</td> -->
|
<!-- <td>Номер оператора</td> -->
|
||||||
<td>Дата время</td>
|
<td>Дата время</td>
|
||||||
<td>Дополнитительная информация</td>
|
<td>Дополнитительная информация</td>
|
||||||
<td>uuid</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -55,10 +54,8 @@
|
|||||||
{% if entry.reason|length > 1 %}
|
{% if entry.reason|length > 1 %}
|
||||||
{{ entry.reason }}
|
{{ entry.reason }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<td> {{ entry.uuid }}</td>
|
|
||||||
</td>
|
</td>
|
||||||
<td> {{ entry.uuid }} </td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</body>
|
</body>
|
||||||
|
@ -1,129 +0,0 @@
|
|||||||
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='incoming-dev')
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
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)
|
|
@ -1,13 +0,0 @@
|
|||||||
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
|
|
||||||
ADD *.py /app
|
|
||||||
EXPOSE 5000
|
|
||||||
|
|
||||||
CMD [".venv/bin/python3", "app.py"]
|
|
@ -1,60 +0,0 @@
|
|||||||
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"
|
|
||||||
})
|
|
@ -1,18 +0,0 @@
|
|||||||
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
|
|
Binary file not shown.
Binary file not shown.
@ -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)
|
|
@ -1,16 +0,0 @@
|
|||||||
|
|
||||||
IMPORTANT_LINE = ['83912051045']
|
|
||||||
|
|
||||||
IGNORE_LIST = ['83912051045',
|
|
||||||
'83912051046',
|
|
||||||
'83919865589',
|
|
||||||
'83919865589',
|
|
||||||
'84950213944',
|
|
||||||
'84951183750',
|
|
||||||
'84951252791',
|
|
||||||
'89919237009',
|
|
||||||
'89919241441',
|
|
||||||
'89919398228',
|
|
||||||
'89919500798',
|
|
||||||
'89919505445',
|
|
||||||
'89919863883']
|
|
@ -1,14 +0,0 @@
|
|||||||
FROM alpine
|
|
||||||
|
|
||||||
RUN apk update && apk upgrade && apk add python3 && apk add -U tzdata
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
COPY requirements.txt requirements.txt
|
|
||||||
ADD *.py /app
|
|
||||||
RUN python3 -m venv .venv
|
|
||||||
RUN /app/.venv/bin/pip3 install -r /app/requirements.txt
|
|
||||||
|
|
||||||
EXPOSE 5000
|
|
||||||
|
|
||||||
CMD [".venv/bin/python3", "app.py"]
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -1,107 +0,0 @@
|
|||||||
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='incoming-dev')
|
|
||||||
|
|
||||||
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)
|
|
@ -1,13 +0,0 @@
|
|||||||
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
|
|
||||||
ADD *.py /app
|
|
||||||
EXPOSE 5000
|
|
||||||
|
|
||||||
CMD [".venv/bin/python3", "app.py"]
|
|
@ -1,60 +0,0 @@
|
|||||||
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"
|
|
||||||
})
|
|
@ -1,18 +0,0 @@
|
|||||||
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
|
|
@ -12,10 +12,14 @@ db_base = db_connection["phone"]
|
|||||||
coll_phone = db_base["phone"]
|
coll_phone = db_base["phone"]
|
||||||
coll_userkey = db_base['userkey']
|
coll_userkey = db_base['userkey']
|
||||||
|
|
||||||
# Stats:
|
#def sendMessage(dt, num):
|
||||||
# 0 - ответили
|
# token = "2035324623:AAGACtvZ551m9V--yTYF9cFuegGejylSsLg"
|
||||||
# 1 - не приняли
|
# chat_id = "-1001941363918"
|
||||||
# 2 - перезвонили успешно
|
# message = "*" + num + "* - " + dt
|
||||||
|
# send_text = 'https://api.telegram.org/bot' + token + '/sendMessage?chat_id=' + chat_id + '&parse_mode=Markdown&text=' + message
|
||||||
|
# response = requests.get(send_text)
|
||||||
|
# return response
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
connection = pika.BlockingConnection(pika.ConnectionParameters(
|
connection = pika.BlockingConnection(pika.ConnectionParameters(
|
||||||
@ -54,14 +58,19 @@ def main():
|
|||||||
insDict = {"client": srcJson['from'], "time": srcJson['time'], "status": 0,
|
insDict = {"client": srcJson['from'], "time": srcJson['time'], "status": 0,
|
||||||
"recordUrl": srcJson["recordUrl"], "duration": srcJson["duration"], "important": tmpIncoming[srcJson['uuid']][2]}
|
"recordUrl": srcJson["recordUrl"], "duration": srcJson["duration"], "important": tmpIncoming[srcJson['uuid']][2]}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# print(srcJson)
|
||||||
print(e)
|
print(e)
|
||||||
insDict = {
|
insDict = {
|
||||||
"client": srcJson['from'], "time": srcJson['time'], "status": 1, "important": tmpIncoming[srcJson['uuid']][2], "uuid": srcJson['uuid']}
|
"client": srcJson['from'], "time": srcJson['time'], "status": 1, "important": tmpIncoming[srcJson['uuid']][2]}
|
||||||
|
#sendMessage(srcJson['time'], srcJson['from'])
|
||||||
finally:
|
finally:
|
||||||
|
print(insDict)
|
||||||
coll_phone.insert_one(insDict)
|
coll_phone.insert_one(insDict)
|
||||||
tmpIncoming.pop(srcJson['uuid'])
|
tmpIncoming.pop(srcJson['uuid'])
|
||||||
try:
|
try:
|
||||||
insUserKey = {'userkey': srcJson['userkey']}
|
insUserKey = {'userkey': srcJson['userkey']}
|
||||||
|
print(insUserKey)
|
||||||
|
print(srcJson['to'])
|
||||||
coll_userkey.update_one(
|
coll_userkey.update_one(
|
||||||
filter={
|
filter={
|
||||||
'operator': srcJson['to'],
|
'operator': srcJson['to'],
|
||||||
@ -75,23 +84,21 @@ def main():
|
|||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
if srcJson['direction'] == 'external':
|
if srcJson['direction'] == 'external':
|
||||||
# coll_phone.update_one({'$and': [{'client': {'$regex': srcJson['to']}}, {'status': 1}}]}, {'$set': {'status': 2, 'callid': srcJson['uuid']}})
|
# coll_phone.update_one({'$and': [{'client': srcJson['to']}, {'status': 1}]}, {
|
||||||
coll_phone.update_one({'$and': [{'client': {'$regex': srcJson['to']}}, {'status': 1}]}, {'$set': {'status': 2, 'callid': srcJson['uuid']}})
|
# '$set': {'status': 2}})
|
||||||
|
r = coll_phone.update_one({'$and': [{'client': {'$regex': srcJson['to']}}, {'status': 1}]}, {
|
||||||
|
'$set': {'status': 2, 'callid': srcJson['uuid']}})
|
||||||
if srcJson['state'] == 'HANGUP':
|
if srcJson['state'] == 'HANGUP':
|
||||||
try:
|
try:
|
||||||
# Проверяем заполнено ли поле recordURL, если нет то меняем статус на 4
|
coll_phone.update_one({'callid':srcJson['uuid']}, {'$set': {'recordUrl': srcJson['recordUrl']}})
|
||||||
if len(srcJson['recordUrl']) > 4:
|
|
||||||
print(srcJson['uuid'], srcJson['recordUrl'])
|
|
||||||
coll_phone.update_one({'callid':srcJson['uuid']}, {'$set': {'recordUrl': srcJson['recordUrl'], 'status': 2}})
|
|
||||||
else:
|
|
||||||
print(srcJson['uuid'])
|
|
||||||
coll_phone.update_one({'callid':srcJson['uuid']}, {'$set': {'status': 4}})
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
print(r)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e.with_traceback)
|
print(e.with_traceback)
|
||||||
print(e)
|
print(e)
|
||||||
|
# print(None)
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
channel.basic_consume(
|
channel.basic_consume(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user