v0.0.1
Разработка: - БД скрипт с начальными данными - вывод списка номеров телефонов по группам
This commit is contained in:
parent
ca5259c638
commit
815b5a6b6a
34 changed files with 1229 additions and 49 deletions
405
source/daster.d
Normal file
405
source/daster.d
Normal file
|
@ -0,0 +1,405 @@
|
|||
module daster;
|
||||
|
||||
import vibe.vibe;
|
||||
import singlog;
|
||||
import readconf;
|
||||
|
||||
import core.stdc.stdlib : exit, EXIT_SUCCESS, EXIT_FAILURE;
|
||||
import std.stdio: writefln;
|
||||
import std.getopt;
|
||||
import std.file;
|
||||
import std.path;
|
||||
import std.algorithm;
|
||||
import std.array;
|
||||
|
||||
import verinfo;
|
||||
import pgdb;
|
||||
import structures;
|
||||
|
||||
import requests.listsgroups;
|
||||
import requests.groupnumbers;
|
||||
|
||||
static ServerInfo serverInfo;
|
||||
|
||||
private void showVersion() {
|
||||
writefln("daster версия %s, собрано %s", getDasterVersion(), __DATE__);
|
||||
}
|
||||
|
||||
int main(string[] args) {
|
||||
log.level(log.INFORMATION);
|
||||
log.output(log.SYSLOG);
|
||||
|
||||
bool flagVersion;
|
||||
string flagSettings;
|
||||
|
||||
try {
|
||||
auto opt = getopt(
|
||||
args,
|
||||
config.bundling,
|
||||
config.caseSensitive,
|
||||
"settings|s",
|
||||
"<файл> Путь к файлу конфигурации settings.conf",
|
||||
&flagSettings,
|
||||
"version|v",
|
||||
"Текущая версия программы",
|
||||
&flagVersion
|
||||
);
|
||||
if (opt.helpWanted) {
|
||||
showVersion();
|
||||
defaultGetoptPrinter(
|
||||
"Использование: daster [ОПЦИИ]...\n",
|
||||
opt.options
|
||||
);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if (flagVersion) {
|
||||
showVersion();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
} catch (GetOptException e) {
|
||||
showVersion();
|
||||
log.c(e.msg);
|
||||
log.i("Попробуйте 'daster -h' для дополнительной информации");
|
||||
log.i("https://git.zhirov.kz/alexander/daster");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!flagSettings.length)
|
||||
flagSettings = "./settings.conf";
|
||||
|
||||
if (!flagSettings.exists) {
|
||||
log.c("Файл конфигурации не найден: " ~ flagSettings);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rc.read(flagSettings);
|
||||
rcAsteriskDB();
|
||||
auto webHost = rcWebHost();
|
||||
|
||||
serverInfo = ServerInfo(webHost.title);
|
||||
|
||||
if (webHost.loglevel != -1) log.level(webHost.loglevel);
|
||||
if (webHost.logoutput) log.output(webHost.logoutput);
|
||||
if (webHost.logfile.length) log.file(webHost.logfile);
|
||||
|
||||
auto router = new URLRouter;
|
||||
router.post("/", &postReq);
|
||||
router.get("/", &getReq);
|
||||
router.get("*", serveStaticFiles(buildPath(webHost.data, "public")));
|
||||
router.get("*", serveStaticFiles(buildPath(webHost.data, "images")));
|
||||
router.get("*", serveStaticFiles(buildPath(webHost.data, "js")));
|
||||
router.get("*", serveStaticFiles(buildPath(webHost.data, "jq")));
|
||||
|
||||
auto memorySessionStore = new MemorySessionStore;
|
||||
|
||||
auto settingsHTTP = new HTTPServerSettings;
|
||||
auto settingsHTTPS = new HTTPServerSettings;
|
||||
|
||||
if (webHost.http) {
|
||||
settingsHTTP.sessionStore = memorySessionStore;
|
||||
settingsHTTP.port = webHost.http;
|
||||
settingsHTTP.bindAddresses = ["::1"] ~ webHost.addresses;
|
||||
}
|
||||
|
||||
if (webHost.https) {
|
||||
settingsHTTPS.sessionStore = memorySessionStore;
|
||||
settingsHTTPS.port = webHost.https;
|
||||
settingsHTTPS.bindAddresses = ["::1"] ~ webHost.addresses;
|
||||
settingsHTTPS.tlsContext = createTLSContext(TLSContextKind.server);
|
||||
settingsHTTPS.tlsContext.useCertificateChainFile(webHost.cert);
|
||||
settingsHTTPS.tlsContext.usePrivateKeyFile(webHost.key);
|
||||
}
|
||||
|
||||
startWebServer(webHost, settingsHTTP, settingsHTTPS, router);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void startWebServer(WebHost wh, HTTPServerSettings http, HTTPServerSettings https, URLRouter router)
|
||||
{
|
||||
if (wh.http && wh.https) {
|
||||
auto listenerHTTP = listenHTTP(http, router);
|
||||
auto listenerHTTPS = listenHTTP(https, router);
|
||||
scope (exit) { listenerHTTP.stopListening(); }
|
||||
scope (exit) { listenerHTTPS.stopListening(); }
|
||||
runApplication();
|
||||
} else if (wh.http) {
|
||||
auto listenerHTTP = listenHTTP(http, router);
|
||||
scope (exit) { listenerHTTP.stopListening(); }
|
||||
runApplication();
|
||||
} else if (wh.https) {
|
||||
auto listenerHTTPS = listenHTTP(https, router);
|
||||
scope (exit) { listenerHTTPS.stopListening(); }
|
||||
runApplication();
|
||||
}
|
||||
}
|
||||
|
||||
void getReq(HTTPServerRequest req, HTTPServerResponse res) {
|
||||
// if (req.session) {
|
||||
// auto user = req.session.get!UserData("userData");
|
||||
// if (user.loggedIn) {
|
||||
// renderMainPage(req, res);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
// render!("index.dt", serverInfo)(res);
|
||||
renderMainPage(req, res);
|
||||
}
|
||||
|
||||
void renderMainPage(HTTPServerRequest req, HTTPServerResponse res) {
|
||||
render!("index.dt", serverInfo)(res);
|
||||
}
|
||||
|
||||
void postReq(HTTPServerRequest req, HTTPServerResponse res) {
|
||||
if (req.method != HTTPMethod.POST) return;
|
||||
|
||||
auto jsr = req.json;
|
||||
string query = jsr["query"].get!string;
|
||||
|
||||
if (query.empty) return;
|
||||
|
||||
// if (query != "authorization" && !checkAuth(req)) {
|
||||
// res.send(
|
||||
// true,
|
||||
// "Сессия не существует. Перезагрузите страницу"
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
|
||||
switch (query) {
|
||||
case "listsgroups":
|
||||
listsgroups(req, res);
|
||||
break;
|
||||
case "groupnumbers":
|
||||
groupnumbers(req, res);
|
||||
break;
|
||||
// case "authorization":
|
||||
// authorization(req, res);
|
||||
// break;
|
||||
// case "logout":
|
||||
// logout(req, res);
|
||||
// break;
|
||||
// case "numbers":
|
||||
// numbers(req, res);
|
||||
// break;
|
||||
// case "add":
|
||||
// addNumber(req, res);
|
||||
// break;
|
||||
// case "write":
|
||||
// writeNumber(req, res);
|
||||
// break;
|
||||
// case "edit":
|
||||
// editNumber(req, res);
|
||||
// break;
|
||||
// case "update":
|
||||
// updateNumber(req, res);
|
||||
// break;
|
||||
// case "remove":
|
||||
// removeNumber(req, res);
|
||||
// break;
|
||||
default:
|
||||
res.redirect("/");
|
||||
}
|
||||
}
|
||||
|
||||
void rcAsteriskDB() {
|
||||
ConfigSection asteriskDB;
|
||||
|
||||
try {
|
||||
asteriskDB = rc[]["daster-db"];
|
||||
} catch (Exception e) {
|
||||
log.c("В конфигурационном файле не верны настройки daster-db");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (asteriskDB["host"].empty) {
|
||||
log.c("В конфигурационном файле не верны настройки daster-db.host");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (asteriskDB["port"].empty) {
|
||||
log.c("В конфигурационном файле не верны настройки daster-db.port");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (asteriskDB["dbname"].empty) {
|
||||
log.c("В конфигурационном файле не верны настройки daster-db.dbname");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (asteriskDB["user"].empty) {
|
||||
log.c("В конфигурационном файле не верны настройки daster-db.user");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
pgsql(
|
||||
"hostaddr=" ~ asteriskDB["host"] ~
|
||||
" port=" ~ asteriskDB["port"] ~
|
||||
" dbname=" ~ asteriskDB["dbname"] ~
|
||||
" user=" ~ asteriskDB["user"] ~
|
||||
" password=" ~ asteriskDB["password"]
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.c(e);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
WebHost rcWebHost() {
|
||||
WebHost wh;
|
||||
ConfigSection webHost;
|
||||
|
||||
try {
|
||||
webHost = rc[]["web-host"];
|
||||
} catch (Exception e) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (webHost["addresses"].empty) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.addresses");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
wh.addresses = webHost["addresses"].to!string.split(',').map!(a => a.strip).array;
|
||||
} catch (Exception e) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.addresses");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (webHost["http"].empty && webHost["https"].empty) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.[http|https]:
|
||||
должен быть указан хотя бы один протокол");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!webHost["http"].empty) {
|
||||
try {
|
||||
wh.http = webHost["http"].to!ushort;
|
||||
} catch (Exception e) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.http");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!webHost["https"].empty) {
|
||||
try {
|
||||
wh.https = webHost["https"].to!ushort;
|
||||
} catch (Exception e) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.https");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!webHost["https"].empty) {
|
||||
if (webHost["cert"].empty || webHost["key"].empty) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.[cert|key]:
|
||||
необходимо указать сертификат и ключ для использования https протокола"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
wh.cert = webHost["cert"];
|
||||
} catch (Exception e) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.cert");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
wh.key = webHost["key"];
|
||||
} catch (Exception e) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.key");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!webHost["data"].empty) {
|
||||
string data;
|
||||
|
||||
try {
|
||||
data = webHost["data"];
|
||||
} catch (Exception e) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.data");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (data.exists) {
|
||||
if (!buildPath(data, "public").exists) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.data - каталог не существует: public");
|
||||
exit(1);
|
||||
}
|
||||
if (!buildPath(data, "js").exists) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.data - каталог не существует: js");
|
||||
exit(1);
|
||||
}
|
||||
if (!buildPath(data, "images").exists) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.data - каталог не существует: images");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.data - каталог не существует: " ~ data);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
wh.data = data;
|
||||
}
|
||||
|
||||
if (!webHost["title"].empty) {
|
||||
try {
|
||||
wh.title = webHost["title"];
|
||||
} catch (Exception e) {
|
||||
log.w("Заголовок не был установлен - web-host.title");
|
||||
}
|
||||
}
|
||||
|
||||
if (!webHost["loglevel"].empty) {
|
||||
try {
|
||||
wh.loglevel = webHost["loglevel"].to!int;
|
||||
if (wh.loglevel < 0 || wh.loglevel > 6)
|
||||
throw new Exception("несуществующий уровень");
|
||||
} catch (Exception e) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.loglevel: " ~ e.msg);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!webHost["logoutput"].empty) {
|
||||
try {
|
||||
wh.logoutput = webHost["logoutput"]
|
||||
.to!string.split(',')
|
||||
.map!((a) {
|
||||
auto flag = a.strip.to!int;
|
||||
|
||||
if ([1, 2, 4].canFind(flag))
|
||||
return flag;
|
||||
|
||||
log.c("В конфигурационном файле не верны настройки web-host.logoutput");
|
||||
exit(1);
|
||||
})
|
||||
.fold!((a, b) => a | b);
|
||||
} catch (Exception e) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.logoutput");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (wh.logoutput & 4) {
|
||||
if (webHost["logfile"].empty) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.logfile");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
wh.logfile = webHost["logfile"];
|
||||
} catch (Exception e) {
|
||||
log.c("В конфигурационном файле не верны настройки web-host.logfile");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wh;
|
||||
}
|
67
source/data.d
Normal file
67
source/data.d
Normal file
|
@ -0,0 +1,67 @@
|
|||
module data;
|
||||
|
||||
import pgdb;
|
||||
import singlog;
|
||||
import structures;
|
||||
|
||||
import std.conv;
|
||||
|
||||
GroupDB[] getListGroups() {
|
||||
GroupDB[] groups;
|
||||
try {
|
||||
auto queryResult = pgsql.sql(
|
||||
"select distinct
|
||||
n.da_group,
|
||||
g.da_comment
|
||||
from da_numbers n
|
||||
left join da_groups g ON g.da_name = n.da_group"
|
||||
);
|
||||
foreach (row; queryResult) {
|
||||
GroupDB data;
|
||||
|
||||
data.name = row["da_group"];
|
||||
data.comment = row["da_comment"];
|
||||
|
||||
groups ~= data;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.e("Не удалось выполнить запрос к БД. " ~ e.msg);
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
NumberDB[] getListNumbers(string group) {
|
||||
NumberDB[] numbers;
|
||||
try {
|
||||
auto queryResult = pgsql.sql(
|
||||
"select
|
||||
dan.da_number,
|
||||
dal.da_comment da_list,
|
||||
dan.da_all_cc,
|
||||
dan.da_white_cc,
|
||||
dan.da_black_cc,
|
||||
dan.da_comment
|
||||
from da_numbers dan
|
||||
left join da_lists dal on dal.da_name = dan.da_list
|
||||
where da_group = ?",
|
||||
group
|
||||
);
|
||||
foreach (row; queryResult) {
|
||||
NumberDB data;
|
||||
|
||||
data.number = row["da_number"];
|
||||
data.list = row["da_list"];
|
||||
data.all_cc = row["da_all_cc"].to!int;
|
||||
data.white_cc = row["da_white_cc"].to!int;
|
||||
data.black_cc = row["da_black_cc"].to!int;
|
||||
data.comment = row["da_comment"];
|
||||
|
||||
numbers ~= data;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.e("Не удалось выполнить запрос к БД. " ~ e.msg);
|
||||
}
|
||||
|
||||
return numbers;
|
||||
}
|
38
source/pgdb.d
Normal file
38
source/pgdb.d
Normal file
|
@ -0,0 +1,38 @@
|
|||
module pgdb;
|
||||
|
||||
import arsd.postgres;
|
||||
import std.stdio;
|
||||
|
||||
alias pgsql = PG.getConnection;
|
||||
|
||||
class PG : PostgreSql {
|
||||
private:
|
||||
static PG _pgsql;
|
||||
this(string config) {
|
||||
super(config);
|
||||
}
|
||||
public:
|
||||
@property static PG getConnection(string config = null) {
|
||||
if (this._pgsql is null) {
|
||||
try {
|
||||
this._pgsql = new PG(config);
|
||||
} catch (Exception e) {
|
||||
throw new Exception(e.msg);
|
||||
}
|
||||
}
|
||||
|
||||
return this._pgsql;
|
||||
}
|
||||
|
||||
PostgresResult sql(T...)(string query, T t) {
|
||||
return cast(PostgresResult)this.query(query, t);
|
||||
}
|
||||
|
||||
void commit() {
|
||||
this.query("COMMIT");
|
||||
}
|
||||
|
||||
void rollback() {
|
||||
this.query("ROLLBACK");
|
||||
}
|
||||
}
|
12
source/requests/groupnumbers.d
Normal file
12
source/requests/groupnumbers.d
Normal file
|
@ -0,0 +1,12 @@
|
|||
module requests.groupnumbers;
|
||||
|
||||
import vibe.vibe;
|
||||
import response;
|
||||
import data;
|
||||
import singlog;
|
||||
|
||||
void groupnumbers(HTTPServerRequest req, HTTPServerResponse res) {
|
||||
auto jsr = req.json;
|
||||
auto listNumbers = getListNumbers(jsr["group"].get!string);
|
||||
render!("group-numbers-list.dt", listNumbers)(res);
|
||||
}
|
11
source/requests/listsgroups.d
Normal file
11
source/requests/listsgroups.d
Normal file
|
@ -0,0 +1,11 @@
|
|||
module requests.listsgroups;
|
||||
|
||||
import vibe.vibe;
|
||||
import response;
|
||||
import data;
|
||||
|
||||
void listsgroups(HTTPServerRequest req, HTTPServerResponse res) {
|
||||
// auto jsr = req.json;
|
||||
|
||||
res.writeJsonBody(getListGroups().serializeToJson());
|
||||
}
|
15
source/response.d
Normal file
15
source/response.d
Normal file
|
@ -0,0 +1,15 @@
|
|||
module response;
|
||||
|
||||
import vibe.vibe;
|
||||
|
||||
struct Res {
|
||||
bool error;
|
||||
string message;
|
||||
string data;
|
||||
}
|
||||
|
||||
void send(HTTPServerResponse res, bool error = false, string message = "", string data = "") {
|
||||
res.writeJsonBody(Res(
|
||||
error, message, data
|
||||
).serializeToJson());
|
||||
}
|
33
source/structures.d
Normal file
33
source/structures.d
Normal file
|
@ -0,0 +1,33 @@
|
|||
module structures;
|
||||
|
||||
struct ServerInfo {
|
||||
string name;
|
||||
}
|
||||
|
||||
struct WebHost {
|
||||
string[] addresses;
|
||||
ushort http = 0;
|
||||
ushort https = 0;
|
||||
string cert;
|
||||
string key;
|
||||
string data;
|
||||
string title;
|
||||
int loglevel = -1;
|
||||
int logoutput = 0;
|
||||
string logfile;
|
||||
}
|
||||
|
||||
struct GroupDB {
|
||||
string name;
|
||||
string comment;
|
||||
}
|
||||
|
||||
struct NumberDB {
|
||||
string number;
|
||||
string group;
|
||||
string list;
|
||||
int all_cc;
|
||||
int white_cc;
|
||||
int black_cc;
|
||||
string comment;
|
||||
}
|
37
source/verinfo.d
Normal file
37
source/verinfo.d
Normal file
|
@ -0,0 +1,37 @@
|
|||
module verinfo;
|
||||
|
||||
import std.algorithm: startsWith;
|
||||
import version_;
|
||||
import std.array : split, join;
|
||||
|
||||
string getDasterVersion() {
|
||||
auto verstr = dasterVersion;
|
||||
if (verstr.startsWith("v"))
|
||||
verstr = verstr[1 .. $];
|
||||
auto parts = verstr.split("-");
|
||||
if (parts.length >= 3) {
|
||||
if (parts[$-1].length == 8 && parts[$-1][1 .. $].isHexNumber() && parts[$-2].isNumber())
|
||||
verstr = parts[0 .. $-2].join("-") ~ "+" ~ parts[$-2 .. $].join("-");
|
||||
}
|
||||
return verstr;
|
||||
}
|
||||
|
||||
private bool isHexNumber(string str) {
|
||||
foreach (ch; str)
|
||||
switch (ch) {
|
||||
case '0': .. case '9': break;
|
||||
case 'a': .. case 'f': break;
|
||||
case 'A': .. case 'F': break;
|
||||
default: return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool isNumber(string str) {
|
||||
foreach (ch; str)
|
||||
switch (ch) {
|
||||
case '0': .. case '9': break;
|
||||
default: return false;
|
||||
}
|
||||
return true;
|
||||
}
|
3
source/version_.d
Normal file
3
source/version_.d
Normal file
|
@ -0,0 +1,3 @@
|
|||
module version_;
|
||||
|
||||
enum dasterVersion = "v0.0.1";
|
Loading…
Add table
Add a link
Reference in a new issue