Files
dm-cli/dm-cli/Deals.cpp
Vladimir N. Korotenko 300fcb98f7 close #16 fix return value
2025-11-22 13:00:01 +03:00

428 lines
11 KiB
C++

#include "Deals.hpp"
#include <string>
#include <cstdlib>
#include "PrintFile.hpp"
#include "common.hpp"
#include "ExecCommand.hpp"
#include "json.hpp"
#include "base64.h"
#include <fstream>
#include "cleanHtml.h"
#include <sstream>
#include <iostream>
#include <ctime>
using namespace std;
using json = nlohmann::json;
int Deals::HelpCreate() const
{
if (isRussian)
PrintFile(DEALS_RU);
else
PrintFile(DEALS_EN);
return 0;
}
int Deals::HelpDealStatus() const
{
if (isRussian)
PrintFile(DEAL_STATUS_RU);
else
PrintFile(DEAL_STATUS_EN);
return 0;
}
int Deals::HelpDealComplete() const
{
if (isRussian)
PrintFile(DEAL_COMPLETE_RU);
else
PrintFile(DEAL_COMPLETE_EN);
return 0;
}
int Deals::HelpDealCancel() const
{
if (isRussian)
PrintFile(DEAL_CANCEL_RU);
else
PrintFile(DEAL_CANCEL_EN);
return 0;
}
int Deals::HelpDealNegative() const
{
if (isRussian)
PrintFile(DEAL_NEGATIVE_RU);
else
PrintFile(DEAL_NEGATIVE_EN);
return 0;
}
Deals::Deals(const InputParser &parser, const bool isRussian, const string address, bool isDebug)
{
this->parser = parser;
this->isRussian = isRussian;
this->address = address;
this->isDebug = isDebug;
}
int Deals::Process()
{
if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("create") && (this->parser.cmdOptionExists("--help") || parser.cmdOptionExists("-h")))
return this->HelpCreate();
if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("status") && (this->parser.cmdOptionExists("--help") || parser.cmdOptionExists("-h")))
return this->HelpDealStatus();
if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("complete") && (this->parser.cmdOptionExists("--help") || parser.cmdOptionExists("-h")))
return this->HelpDealComplete();
if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("cancel") && (this->parser.cmdOptionExists("--help") || parser.cmdOptionExists("-h")))
return this->HelpDealCancel();
if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("negative") && (this->parser.cmdOptionExists("--help") || parser.cmdOptionExists("-h")))
return this->HelpDealNegative();
return Update();
return 0;
}
int Deals::Update()
{
if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("create"))
return Create();
if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("status"))
return Status();
if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("complete"))
return Complite();
if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("cancel"))
return Cancel();
if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("negative"))
return Negative();
return 1;
}
int Deals::Create()
{
string at;
string seller;
string customer;
string type;
string sum;
string leave_before;
string pay;
at = GetVal("-a", "--at");
if (at.length() == 0)
at = "https://testnet-dm2.bitdeals.org";
seller = GetVal("-s", "--seller");
customer = GetVal("-c", "--customer");
type = GetVal("-t", "--type");
sum = GetVal("-g", "--sum");
leave_before = GetVal("-l", "--leave_before");
pay = GetVal("-p", "--pay");
// start curl
string data("");
data += ReadFile(DEAL_CREATE_TPL);
data = Replace(data, string("{{ADDRESS}}"), address);
data = Replace(data, string("{{AT}}"), at);
data = Replace(data, string("{{TYPE}}"), type);
data = Replace(data, string("{{SELLER}}"), seller);
data = Replace(data, string("{{CUSTOMER}}"), customer);
data = Replace(data, string("{{SUM}}"), sum);
if (pay.length() == 0)
{
//{{UNTIL}}
data = Replace(data, string("{{UNTIL}}"), "");
}
else
{
pay = GetDate(pay);
string untl(",\"until\": \"");
untl.append(pay);
untl.append("\"");
data = Replace(data, string("{{UNTIL}}"), untl);
}
if (leave_before.length() == 0)
{
//{{FEETBACK}}
data = Replace(data, string("{{FEETBACK}}"), "");
}
else
{
leave_before = GetDate(leave_before);
string untl(",\"feedback\": {\"leave-before\": \"");
untl.append(leave_before);
untl.append("\"}");
data = Replace(data, string("{{FEETBACK}}"), untl);
}
string result = ExecCommand(data.c_str());
if (result.length() == 0)
return NoResponse("");
nlohmann::json jsonData = nlohmann::json::parse(result);
std::ostringstream stream;
stream << "success: " << jsonData["result"]["success"] << endl;
stream << "message: " << jsonData["result"]["message"] << endl;
string decoded = stream.str();
cout << decoded << endl;
string payload = cleanup_html(base64_decode(jsonData["payload"]));
if (isDebug)
ShowDebug(data, decoded, 1, payload);
return 0;
}
string Deals::GetDate(const string date)
{
string buffer = date;
/*
-p|--pay { <yyyy-mm-dd> [hh:mm:ss UTC] | <time>[smhd] }
Time for make payment; default: 1d
*/
std::transform(buffer.begin(), buffer.end(), buffer.begin(), ::toupper);
if (buffer.length() < 23)
{
char letter = buffer[buffer.length() - 1];
int append = 0;
string numval = buffer.substr(0, buffer.length() - 1);
int num = stoi(numval);
switch (letter)
{
case 'S':
append = num;
break;
case 'M':
append = num * 60;
break;
case 'H':
append = num * 60 * 60;
break;
case 'D':
append = num * 24 * 60 * 60;
break;
default:
break;
}
std::time_t utcTimeInSeconds = std::time(nullptr);
utcTimeInSeconds += append;
tm *tmm = gmtime(&utcTimeInSeconds);
char buff[70];
strftime(buff, sizeof buff, "%Y-%m-%d %H:%M:%S", tmm);
string result = buff;
return result;
}
else
{
return buffer;
}
}
string Deals::CommonStatus()
{
string payaddress = parser.getLast();
string data("curl -s -X POST \"");
data.append(address);
data.append("/api/v1/deal/status\" -H \"Content-Type: application/json\" ");
data.append("-d \"{\\\"address\\\":\\\"");
data.append(payaddress);
data.append("\\\"}\"");
return data;
}
int Deals::Status()
{
string data = CommonStatus();
string result = ExecCommand(data.c_str());
if (result.length() == 0)
return NoResponse("");
nlohmann::json jsonData = nlohmann::json::parse(result);
std::ostringstream stream;
bool isPayment = false;
string payload = cleanup_html(base64_decode(jsonData["payload"]));
stream << payload << endl;
// order: Paid, order: Completed, order: Executed
if (payload.find("Paid") >= 0 || payload.find("Completed") >= 0 || payload.find("Executed") >= 0)
{
isPayment = true;
}
string decoded = stream.str();
cout << decoded << endl;
if (isDebug)
ShowDebug(data, decoded, 1, payload);
if (parser.cmdOptionExists("-i") || parser.cmdOptionExists("--is-paid"))
{
return isPayment == true ? 0 : 1;
}
return 0;
}
int Deals::Complite()
{
string data = CommonStatus();
string result = ExecCommand(data.c_str());
if (result.length() == 0)
return NoResponse("");
nlohmann::json jsonData = nlohmann::json::parse(result);
nlohmann::json deal = jsonData["deal"];
string positive = "Positive";
int refund = 0;
if (parser.cmdOptionExists("-p") || parser.cmdOptionExists("--positive"))
{
positive = GetVal("-p", "--positive");
}
if (parser.cmdOptionExists("--refund"))
{
refund = stoi(parser.getCmdOption("--refund"));
}
if (parser.cmdOptionExists("-r"))
{
refund = stoi(parser.getCmdOption("-r"));
}
deal["feedback"]["status"] = positive;
if (refund > 0)
deal["feedback"]["refund"] = refund;
string jsf = deal.dump();
jsf = ReplaceAll(jsf, "\"", "\\\"");
data = "curl -s -X POST \"";
data.append(address);
data.append("/api/v1/deal/complete\" -H \"Content-Type: application/json\" ");
data.append("-d \"");
data.append(jsf);
data.append("\"");
result = ExecCommand(data.c_str());
if (result.length() == 0)
return NoResponse("");
std::ostringstream stream;
stream << "success: " << jsonData["result"]["success"] << endl;
stream << "message: " << jsonData["result"]["message"] << endl;
string decoded = stream.str();
std::cout << decoded << endl;
if (isDebug)
ShowDebug(data, decoded, 0, result);
return 0;
}
int Deals::Cancel()
{
string data = CommonStatus();
string result = ExecCommand(data.c_str());
if (result.length() == 0)
return NoResponse("");
nlohmann::json jsonData = nlohmann::json::parse(result);
nlohmann::json deal = jsonData["deal"];
string message;
string sign;
if (parser.cmdOptionExists("-m") || parser.cmdOptionExists("--message"))
{
message = GetVal("-m", "--message");
}
if (parser.cmdOptionExists("-s") || parser.cmdOptionExists("--signature"))
{
sign = GetVal("-s", "--signature");
}
deal["seller"]["signature"] = sign;
deal["feedback"]["comments"] = message;
string jsf = deal.dump();
jsf = ReplaceAll(jsf, "\"", "\\\"");
data = "curl -s -X POST \"";
data.append(address);
data.append("/api/v1/deal/cancel\" -H \"Content-Type: application/json\" ");
data.append("-d \"");
data.append(jsf);
data.append("\"");
result = ExecCommand(data.c_str());
if (result.length() == 0)
return NoResponse("");
std::ostringstream stream;
stream << "success: " << jsonData["result"]["success"] << endl;
stream << "message: " << jsonData["result"]["message"] << endl;
string decoded = stream.str();
std::cout << decoded << endl;
if (isDebug)
ShowDebug(data, decoded, 0, result);
return 0;
}
int Deals::Negative()
{
string data = CommonStatus();
string result = ExecCommand(data.c_str());
if (result.length() == 0)
return NoResponse("");
nlohmann::json jsonData = nlohmann::json::parse(result);
nlohmann::json deal = jsonData["deal"];
string message;
string sign;
if (parser.cmdOptionExists("-m") || parser.cmdOptionExists("--message"))
{
message = GetVal("-m", "--message");
}
if (parser.cmdOptionExists("-s") || parser.cmdOptionExists("--signature"))
{
sign = GetVal("-s", "--signature");
}
deal["seller"]["signature"] = sign;
deal["feedback"]["comments"] = message;
string jsf = deal.dump();
jsf = ReplaceAll(jsf, "\"", "\\\"");
data = "curl -s -X POST \"";
data.append(address);
data.append("/api/v1/deal/feedback\" -H \"Content-Type: application/json\" ");
data.append("-d \"");
data.append(jsf);
data.append("\"");
result = ExecCommand(data.c_str());
if (result.length() == 0)
return NoResponse("");
std::ostringstream stream;
stream << "success: " << jsonData["result"]["success"] << endl;
stream << "message: " << jsonData["result"]["message"] << endl;
string decoded = stream.str();
std::cout << decoded << endl;
if (isDebug)
ShowDebug(data, decoded, 0, result);
return 0;
}
string Deals::GetVal(const string first, const string second)
{
string aval;
string res("");
if (parser.cmdOptionExists(first))
{
aval = parser.getCmdOption(first);
if (aval.length() > 0)
res = aval;
}
if (parser.cmdOptionExists(second))
{
aval = parser.getCmdOption(second);
if (aval.length() > 0)
res = aval;
}
return res;
}