Finish implementation and tests for the cheat system #3
125
handler/agora.py
125
handler/agora.py
|
@ -95,16 +95,15 @@ class Agora(object):
|
||||||
reference = self.tx.tx_to_ref(contact_id)
|
reference = self.tx.tx_to_ref(contact_id)
|
||||||
buyer = contact["data"]["buyer"]["username"]
|
buyer = contact["data"]["buyer"]["username"]
|
||||||
amount = contact["data"]["amount"]
|
amount = contact["data"]["amount"]
|
||||||
if "amount_xmr" in contact["data"]:
|
asset = contact["data"]["advertisement"]["asset"]
|
||||||
|
if asset == "XMR":
|
||||||
amount_crypto = contact["data"]["amount_xmr"]
|
amount_crypto = contact["data"]["amount_xmr"]
|
||||||
crypto = "XMR"
|
elif asset == "BTC":
|
||||||
elif "amount_btc" in contact["data"]:
|
|
||||||
amount_crypto = contact["data"]["amount_btc"]
|
amount_crypto = contact["data"]["amount_btc"]
|
||||||
crypto = "BTC"
|
|
||||||
currency = contact["data"]["currency"]
|
currency = contact["data"]["currency"]
|
||||||
if not contact["data"]["is_selling"]:
|
if not contact["data"]["is_selling"]:
|
||||||
continue
|
continue
|
||||||
rtrn.append(f"{reference}: {buyer} {amount}{currency} {amount_crypto}{crypto}")
|
rtrn.append(f"{reference}: {buyer} {amount}{currency} {amount_crypto}{asset}")
|
||||||
return rtrn
|
return rtrn
|
||||||
|
|
||||||
def dashboard_hook(self, dash):
|
def dashboard_hook(self, dash):
|
||||||
|
@ -123,22 +122,21 @@ class Agora(object):
|
||||||
current_trades.append(reference)
|
current_trades.append(reference)
|
||||||
buyer = contact["data"]["buyer"]["username"]
|
buyer = contact["data"]["buyer"]["username"]
|
||||||
amount = contact["data"]["amount"]
|
amount = contact["data"]["amount"]
|
||||||
if "amount_xmr" in contact["data"]:
|
asset = contact["data"]["advertisement"]["asset"]
|
||||||
|
if asset == "XMR":
|
||||||
amount_crypto = contact["data"]["amount_xmr"]
|
amount_crypto = contact["data"]["amount_xmr"]
|
||||||
crypto = "XMR"
|
elif asset == "BTC":
|
||||||
elif "amount_btc" in contact["data"]:
|
|
||||||
amount_crypto = contact["data"]["amount_btc"]
|
amount_crypto = contact["data"]["amount_btc"]
|
||||||
crypto = "BTC"
|
|
||||||
currency = contact["data"]["currency"]
|
currency = contact["data"]["currency"]
|
||||||
if not contact["data"]["is_selling"]:
|
if not contact["data"]["is_selling"]:
|
||||||
continue
|
continue
|
||||||
if reference not in self.last_dash:
|
if reference not in self.last_dash:
|
||||||
reference = self.tx.new_trade(contact_id, buyer, currency, amount, amount_xmr)
|
reference = self.tx.new_trade(asset, contact_id, buyer, currency, amount, amount_crypto)
|
||||||
if reference:
|
if reference:
|
||||||
if reference not in current_trades:
|
if reference not in current_trades:
|
||||||
current_trades.append(reference)
|
current_trades.append(reference)
|
||||||
# Let us know there is a new trade
|
# Let us know there is a new trade
|
||||||
self.irc.sendmsg(f"AUTO {reference}: {buyer} {amount}{currency} {amount_crypto}{crypto}")
|
self.irc.sendmsg(f"AUTO {reference}: {buyer} {amount}{currency} {amount_crypto}{asset}")
|
||||||
# Note that we have seen this reference
|
# Note that we have seen this reference
|
||||||
self.last_dash.add(reference)
|
self.last_dash.add(reference)
|
||||||
|
|
||||||
|
@ -167,12 +165,11 @@ class Agora(object):
|
||||||
contact_id = contact["data"]["contact_id"]
|
contact_id = contact["data"]["contact_id"]
|
||||||
buyer = contact["data"]["buyer"]["username"]
|
buyer = contact["data"]["buyer"]["username"]
|
||||||
amount = contact["data"]["amount"]
|
amount = contact["data"]["amount"]
|
||||||
if "amount_xmr" in contact["data"]:
|
asset = contact["data"]["advertisement"]["asset"]
|
||||||
|
if asset == "XMR":
|
||||||
amount_crypto = contact["data"]["amount_xmr"]
|
amount_crypto = contact["data"]["amount_xmr"]
|
||||||
crypto = "XMR"
|
elif asset == "BTC":
|
||||||
elif "amount_btc" in contact["data"]:
|
|
||||||
amount_crypto = contact["data"]["amount_btc"]
|
amount_crypto = contact["data"]["amount_btc"]
|
||||||
crypto = "BTC"
|
|
||||||
currency = contact["data"]["currency"]
|
currency = contact["data"]["currency"]
|
||||||
release_url = contact["actions"]["release_url"]
|
release_url = contact["actions"]["release_url"]
|
||||||
if not contact["data"]["is_selling"]:
|
if not contact["data"]["is_selling"]:
|
||||||
|
@ -180,7 +177,7 @@ class Agora(object):
|
||||||
reference = self.tx.tx_to_ref(contact_id)
|
reference = self.tx.tx_to_ref(contact_id)
|
||||||
if not reference:
|
if not reference:
|
||||||
reference = "not_set"
|
reference = "not_set"
|
||||||
dash_tmp.append(f"{reference}: {buyer} {amount}{currency} {amount_crypto}{crypto} {release_url}")
|
dash_tmp.append(f"{reference}: {buyer} {amount}{currency} {amount_crypto}{asset} {release_url}")
|
||||||
|
|
||||||
return dash_tmp
|
return dash_tmp
|
||||||
|
|
||||||
|
@ -443,10 +440,12 @@ class Agora(object):
|
||||||
max_local = max_usd * rates[currency]
|
max_local = max_usd * rates[currency]
|
||||||
return (min_local, max_local)
|
return (min_local, max_local)
|
||||||
|
|
||||||
def create_ad(self, countrycode, currency):
|
def create_ad(self, asset, countrycode, currency):
|
||||||
"""
|
"""
|
||||||
Post an ad in a country with a given currency.
|
Post an ad with the given asset in a country with a given currency.
|
||||||
Convert the min and max amounts from settings to the given currency with CurrencyRates.
|
Convert the min and max amounts from settings to the given currency with CurrencyRates.
|
||||||
|
:param asset: the crypto asset to list (XMR or BTC)
|
||||||
|
:type asset: string
|
||||||
:param countrycode: country code
|
:param countrycode: country code
|
||||||
:param currency: currency code
|
:param currency: currency code
|
||||||
:type countrycode: string
|
:type countrycode: string
|
||||||
|
@ -463,6 +462,7 @@ class Agora(object):
|
||||||
else:
|
else:
|
||||||
adtext = ad.replace("$PAYMENT$", settings.Agora.DefaultDetailsAd)
|
adtext = ad.replace("$PAYMENT$", settings.Agora.DefaultDetailsAd)
|
||||||
paymentdetailstext = paymentdetails.replace("$PAYMENT$", settings.Agora.DefaultDetailsPayment)
|
paymentdetailstext = paymentdetails.replace("$PAYMENT$", settings.Agora.DefaultDetailsPayment)
|
||||||
|
ad = ad.replace("$ASSET$", asset)
|
||||||
rates = self.get_rates_all()
|
rates = self.get_rates_all()
|
||||||
if currency == "USD":
|
if currency == "USD":
|
||||||
min_amount = float(settings.Agora.MinUSD)
|
min_amount = float(settings.Agora.MinUSD)
|
||||||
|
@ -478,7 +478,7 @@ class Agora(object):
|
||||||
country_code=countrycode,
|
country_code=countrycode,
|
||||||
currency=currency,
|
currency=currency,
|
||||||
trade_type="ONLINE_SELL",
|
trade_type="ONLINE_SELL",
|
||||||
asset="XMR",
|
asset=asset,
|
||||||
price_equation=price_formula,
|
price_equation=price_formula,
|
||||||
track_max_amount=False,
|
track_max_amount=False,
|
||||||
require_trusted_by_advertiser=False,
|
require_trusted_by_advertiser=False,
|
||||||
|
@ -500,52 +500,53 @@ class Agora(object):
|
||||||
:return: False or dict with response
|
:return: False or dict with response
|
||||||
:rtype: bool or dict
|
:rtype: bool or dict
|
||||||
"""
|
"""
|
||||||
for currency, countrycode in loads(settings.Agora.DistList):
|
for asset in loads(settings.Agora.AssetList):
|
||||||
rtrn = self.create_ad(countrycode, currency)
|
for currency, countrycode in loads(settings.Agora.DistList):
|
||||||
if not rtrn:
|
rtrn = self.create_ad(asset, countrycode, currency)
|
||||||
return False
|
|
||||||
yield rtrn
|
|
||||||
|
|
||||||
def get_combinations(self):
|
|
||||||
"""
|
|
||||||
Get all combinations of currencies and countries from the configuration.
|
|
||||||
:return: list of [country, currency]
|
|
||||||
:rtype: list
|
|
||||||
"""
|
|
||||||
currencies = loads(settings.Agora.BruteCurrencies)
|
|
||||||
countries = loads(settings.Agora.BruteCountries)
|
|
||||||
combinations = [[country, currency] for country in countries for currency in currencies]
|
|
||||||
return combinations
|
|
||||||
|
|
||||||
def dist_bruteforce(self):
|
|
||||||
"""
|
|
||||||
Bruteforce all possible ads from the currencies and countries in the config.
|
|
||||||
Does not exit on errors.
|
|
||||||
:return: False or dict with response
|
|
||||||
:rtype: bool or dict
|
|
||||||
"""
|
|
||||||
combinations = self.get_combinations()
|
|
||||||
for country, currency in combinations:
|
|
||||||
rtrn = self.create_ad(country, currency)
|
|
||||||
if not rtrn:
|
|
||||||
yield False
|
|
||||||
yield rtrn
|
|
||||||
|
|
||||||
def bruteforce_fill_blanks(self):
|
|
||||||
"""
|
|
||||||
Get the ads that we want to configure but have not, and fill in the blanks.
|
|
||||||
:return: False or dict with response
|
|
||||||
:rtype: bool or dict
|
|
||||||
"""
|
|
||||||
existing_ads = self.enum_ads()
|
|
||||||
combinations = self.get_combinations()
|
|
||||||
for country, currency in combinations:
|
|
||||||
if not [country, currency] in existing_ads:
|
|
||||||
rtrn = self.create_ad(country, currency)
|
|
||||||
if not rtrn:
|
if not rtrn:
|
||||||
yield False
|
return False
|
||||||
yield rtrn
|
yield rtrn
|
||||||
|
|
||||||
|
# def get_combinations(self):
|
||||||
|
# """
|
||||||
|
# Get all combinations of currencies and countries from the configuration.
|
||||||
|
# :return: list of [country, currency]
|
||||||
|
# :rtype: list
|
||||||
|
# """
|
||||||
|
# currencies = loads(settings.Agora.BruteCurrencies)
|
||||||
|
# countries = loads(settings.Agora.BruteCountries)
|
||||||
|
# combinations = [[country, currency] for country in countries for currency in currencies]
|
||||||
|
# return combinations
|
||||||
|
|
||||||
|
# def dist_bruteforce(self):
|
||||||
|
# """
|
||||||
|
# Bruteforce all possible ads from the currencies and countries in the config.
|
||||||
|
# Does not exit on errors.
|
||||||
|
# :return: False or dict with response
|
||||||
|
# :rtype: bool or dict
|
||||||
|
# """
|
||||||
|
# combinations = self.get_combinations()
|
||||||
|
# for country, currency in combinations:
|
||||||
|
# rtrn = self.create_ad(country, currency)
|
||||||
|
# if not rtrn:
|
||||||
|
# yield False
|
||||||
|
# yield rtrn
|
||||||
|
#
|
||||||
|
# def bruteforce_fill_blanks(self):
|
||||||
|
# """
|
||||||
|
# Get the ads that we want to configure but have not, and fill in the blanks.
|
||||||
|
# :return: False or dict with response
|
||||||
|
# :rtype: bool or dict
|
||||||
|
# """
|
||||||
|
# existing_ads = self.enum_ads()
|
||||||
|
# combinations = self.get_combinations()
|
||||||
|
# for country, currency in combinations:
|
||||||
|
# if not [country, currency] in existing_ads:
|
||||||
|
# rtrn = self.create_ad(country, currency)
|
||||||
|
# if not rtrn:
|
||||||
|
# yield False
|
||||||
|
# yield rtrn
|
||||||
|
|
||||||
def strip_duplicate_ads(self):
|
def strip_duplicate_ads(self):
|
||||||
"""
|
"""
|
||||||
Remove duplicate ads.
|
Remove duplicate ads.
|
||||||
|
|
|
@ -33,11 +33,15 @@ class IRCCommands(object):
|
||||||
"""
|
"""
|
||||||
Post an ad on AgoraDesk with the given country and currency code.
|
Post an ad on AgoraDesk with the given country and currency code.
|
||||||
"""
|
"""
|
||||||
posted = agora.create_ad(spl[1], spl[2])
|
if length == 4:
|
||||||
if posted["success"]:
|
if spl[1] not in loads(settings.Agora.AssetList):
|
||||||
msg(f"{posted['response']['data']['message']}: {posted['response']['data']['ad_id']}")
|
msg(f"Not a valid asset: {spl[1]}")
|
||||||
else:
|
return
|
||||||
msg(dumps(posted["response"]))
|
posted = agora.create_ad(spl[1], spl[2], spl[3])
|
||||||
|
if posted["success"]:
|
||||||
|
msg(f"{posted['response']['data']['message']}: {posted['response']['data']['ad_id']}")
|
||||||
|
else:
|
||||||
|
msg(dumps(posted["response"]))
|
||||||
|
|
||||||
class messages(object):
|
class messages(object):
|
||||||
name = "messages"
|
name = "messages"
|
||||||
|
@ -87,31 +91,31 @@ class IRCCommands(object):
|
||||||
else:
|
else:
|
||||||
msg(x["response"]["data"]["message"])
|
msg(x["response"]["data"]["message"])
|
||||||
|
|
||||||
class brute(object):
|
# class brute(object):
|
||||||
name = "brute"
|
# name = "brute"
|
||||||
authed = True
|
# authed = True
|
||||||
helptext = "Use a bruteforce algorithm to create all possible currency and country pairs."
|
# helptext = "Use a bruteforce algorithm to create all possible currency and country pairs."
|
||||||
|
#
|
||||||
@staticmethod
|
# @staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx):
|
# def run(cmd, spl, length, authed, msg, agora, revolut, tx):
|
||||||
for x in agora.dist_bruteforce():
|
# for x in agora.dist_bruteforce():
|
||||||
if x["success"]:
|
# if x["success"]:
|
||||||
msg(f"{x['response']['data']['message']}: {x['response']['data']['ad_id']}")
|
# msg(f"{x['response']['data']['message']}: {x['response']['data']['ad_id']}")
|
||||||
else:
|
# else:
|
||||||
msg(dumps(x))
|
# msg(dumps(x))
|
||||||
|
#
|
||||||
class fillblanks(object):
|
# class fillblanks(object):
|
||||||
name = "fillblanks"
|
# name = "fillblanks"
|
||||||
authed = True
|
# authed = True
|
||||||
helptext = "Resume a run of brute by getting all our adverts then filling the blanks."
|
# helptext = "Resume a run of brute by getting all our adverts then filling the blanks."
|
||||||
|
#
|
||||||
@staticmethod
|
# @staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx):
|
# def run(cmd, spl, length, authed, msg, agora, revolut, tx):
|
||||||
for x in agora.bruteforce_fill_blanks():
|
# for x in agora.bruteforce_fill_blanks():
|
||||||
if x["success"]:
|
# if x["success"]:
|
||||||
msg(f"{x['response']['data']['message']}: {x['response']['data']['ad_id']}")
|
# msg(f"{x['response']['data']['message']}: {x['response']['data']['ad_id']}")
|
||||||
else:
|
# else:
|
||||||
msg(dumps(x))
|
# msg(dumps(x))
|
||||||
|
|
||||||
class stripdupes(object):
|
class stripdupes(object):
|
||||||
name = "stripdupes"
|
name = "stripdupes"
|
||||||
|
@ -190,16 +194,30 @@ class IRCCommands(object):
|
||||||
if total_usd_revolut is False:
|
if total_usd_revolut is False:
|
||||||
msg("Error getting Revolut balance.")
|
msg("Error getting Revolut balance.")
|
||||||
return
|
return
|
||||||
agora_wallet = agora.agora.wallet_balance_xmr()
|
agora_wallet_xmr = agora.agora.wallet_balance_xmr()
|
||||||
if not agora_wallet["success"]:
|
if not agora_wallet_xmr["success"]:
|
||||||
msg("Error getting Agora balance.")
|
msg("Error getting Agora XMR balance.")
|
||||||
return
|
return
|
||||||
total_xmr_agora = agora_wallet["response"]["data"]["total"]["balance"]
|
agora_wallet_btc = agora.agora.wallet_balance_btc()
|
||||||
|
if not agora_wallet_btc["success"]:
|
||||||
|
msg("Error getting Agora BTC balance.")
|
||||||
|
return
|
||||||
|
total_xmr_agora = agora_wallet_xmr["response"]["data"]["total"]["balance"]
|
||||||
|
total_btc_agora = agora_wallet_btc["response"]["data"]["total"]["balance"]
|
||||||
# Get the XMR -> USD exchange rate
|
# Get the XMR -> USD exchange rate
|
||||||
xmr_usd = agora.cg.get_price(ids="monero", vs_currencies=["USD"])
|
xmr_usd = agora.cg.get_price(ids="monero", vs_currencies=["USD"])
|
||||||
|
|
||||||
|
# Get the BTC -> USD exchange rate
|
||||||
|
btc_usd = agora.cg.get_price(ids="bitcoin", vs_currencies=["USD"])
|
||||||
|
|
||||||
# Convert the Agora XMR total to USD
|
# Convert the Agora XMR total to USD
|
||||||
total_usd_agora = float(total_xmr_agora) * xmr_usd["monero"]["usd"]
|
total_usd_agora_xmr = float(total_xmr_agora) * xmr_usd["monero"]["usd"]
|
||||||
|
|
||||||
|
# Convert the Agora BTC total to USD
|
||||||
|
total_usd_agora_btc = float(total_btc_agora) * btc_usd["bitcoin"]["usd"]
|
||||||
|
|
||||||
|
# Add it all up
|
||||||
|
total_usd_agora = total_usd_agora_xmr + total_usd_agora_btc
|
||||||
total_usd = total_usd_agora + total_usd_revolut
|
total_usd = total_usd_agora + total_usd_revolut
|
||||||
|
|
||||||
# Convert the total USD price to GBP and SEK
|
# Convert the total USD price to GBP and SEK
|
||||||
|
@ -315,16 +333,22 @@ class IRCCommands(object):
|
||||||
class wallet(object):
|
class wallet(object):
|
||||||
name = "wallet"
|
name = "wallet"
|
||||||
authed = True
|
authed = True
|
||||||
helptext = "Get Agora wallet balance in XMR."
|
helptext = "Get Agora wallet balances."
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx):
|
def run(cmd, spl, length, authed, msg, agora, revolut, tx):
|
||||||
rtrn = agora.agora.wallet_balance_xmr()
|
rtrn_xmr = agora.agora.wallet_balance_xmr()
|
||||||
if not rtrn["success"]:
|
if not rtrn_xmr["success"]:
|
||||||
msg("Error getting wallet details.")
|
msg("Error getting XMR wallet details.")
|
||||||
return
|
return
|
||||||
balance = rtrn["response"]["data"]["total"]["balance"]
|
rtrn_btc = agora.agora.wallet_balance()
|
||||||
msg(f"Wallet balance: {balance}XMR")
|
if not rtrn_btc["success"]:
|
||||||
|
msg("Error getting BTC wallet details.")
|
||||||
|
return
|
||||||
|
balance_xmr = rtrn_xmr["response"]["data"]["total"]["balance"]
|
||||||
|
balance_btc = rtrn_btc["response"]["data"]["total"]["balance"]
|
||||||
|
msg(f"XMR wallet balance: {balance_xmr}")
|
||||||
|
msg(f"BTC wallet balance: {balance_btc}")
|
||||||
|
|
||||||
class pubads(object):
|
class pubads(object):
|
||||||
name = "pubads"
|
name = "pubads"
|
||||||
|
|
|
@ -183,22 +183,23 @@ class Transactions(object):
|
||||||
message_long = rtrn["response"]["data"]["message"]
|
message_long = rtrn["response"]["data"]["message"]
|
||||||
self.irc.sendmsg(f"{message} - {message_long}")
|
self.irc.sendmsg(f"{message} - {message_long}")
|
||||||
|
|
||||||
def new_trade(self, trade_id, buyer, currency, amount, amount_xmr):
|
def new_trade(self, asset, trade_id, buyer, currency, amount, amount_crypto):
|
||||||
"""
|
"""
|
||||||
Called when we have a new trade in Agora.
|
Called when we have a new trade in Agora.
|
||||||
Store details in Redis, generate a reference and optionally let the customer know the reference.
|
Store details in Redis, generate a reference and optionally let the customer know the reference.
|
||||||
"""
|
"""
|
||||||
reference = "".join(choices(ascii_uppercase, k=5))
|
reference = "".join(choices(ascii_uppercase, k=5))
|
||||||
reference = f"XMR-{reference}"
|
reference = f"{asset}-{reference}"
|
||||||
existing_ref = r.get(f"trade.{trade_id}.reference")
|
existing_ref = r.get(f"trade.{trade_id}.reference")
|
||||||
if not existing_ref:
|
if not existing_ref:
|
||||||
r.set(f"trade.{trade_id}.reference", reference)
|
r.set(f"trade.{trade_id}.reference", reference)
|
||||||
to_store = {
|
to_store = {
|
||||||
"id": trade_id,
|
"id": trade_id,
|
||||||
|
"asset": asset,
|
||||||
"buyer": buyer,
|
"buyer": buyer,
|
||||||
"currency": currency,
|
"currency": currency,
|
||||||
"amount": amount,
|
"amount": amount,
|
||||||
"amount_xmr": amount_xmr,
|
"amount_crypto": amount_crypto,
|
||||||
"reference": reference,
|
"reference": reference,
|
||||||
}
|
}
|
||||||
self.log.info("Storing trade information: {info}", info=str(to_store))
|
self.log.info("Storing trade information: {info}", info=str(to_store))
|
||||||
|
|
Loading…
Reference in New Issue