|
|
|
@ -5,6 +5,7 @@ from datetime import datetime, timezone
|
|
|
|
|
from random import choices
|
|
|
|
|
from string import ascii_uppercase
|
|
|
|
|
|
|
|
|
|
from aiocoingecko import AsyncCoinGeckoAPISession
|
|
|
|
|
from django.conf import settings
|
|
|
|
|
|
|
|
|
|
from core.clients.platforms.api.agoradesk import AgoraDesk
|
|
|
|
@ -33,7 +34,37 @@ class LocalPlatformClient(ABC):
|
|
|
|
|
Call a method using the self.api object.
|
|
|
|
|
"""
|
|
|
|
|
if hasattr(self.api, method):
|
|
|
|
|
return await getattr(self.api, method)(*args, **kwargs)
|
|
|
|
|
returned_429 = True
|
|
|
|
|
iterations = 0
|
|
|
|
|
throttled = 0
|
|
|
|
|
while returned_429 or iterations == 100:
|
|
|
|
|
response = await getattr(self.api, method)(*args, **kwargs)
|
|
|
|
|
if "status" in response:
|
|
|
|
|
if response["status"] == 429: # Too many requests
|
|
|
|
|
throttled += 1
|
|
|
|
|
sleep_time = pow(throttled, 1.9)
|
|
|
|
|
log.info(
|
|
|
|
|
(
|
|
|
|
|
f"Throttled {throttled} times while calling "
|
|
|
|
|
f"{method}, "
|
|
|
|
|
f"sleeping for {sleep_time} seconds"
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
# We're running in a thread, so this is fine
|
|
|
|
|
await asyncio.sleep(sleep_time)
|
|
|
|
|
elif response["status"] == 400:
|
|
|
|
|
raise Exception(response)
|
|
|
|
|
else:
|
|
|
|
|
if throttled != 0:
|
|
|
|
|
log.info(
|
|
|
|
|
f"Finally successful after {throttled}",
|
|
|
|
|
f" attempts to call {method}",
|
|
|
|
|
)
|
|
|
|
|
returned_429 = False
|
|
|
|
|
throttled = 0
|
|
|
|
|
iterations += 1
|
|
|
|
|
|
|
|
|
|
return response
|
|
|
|
|
else:
|
|
|
|
|
raise Exception(f"Method {method} not found in {self.name} API.")
|
|
|
|
|
|
|
|
|
@ -249,17 +280,16 @@ class LocalPlatformClient(ABC):
|
|
|
|
|
async def enum_ad_ids(self, page=0):
|
|
|
|
|
if self.name == "lbtc" and page == 0:
|
|
|
|
|
page = 1
|
|
|
|
|
ads = await self.api.ads(page=page)
|
|
|
|
|
ads = await self.call("ads", page=page)
|
|
|
|
|
# ads = await self.api._api_call(api_method="ads", query_values={"page": page})
|
|
|
|
|
if ads is False:
|
|
|
|
|
return False
|
|
|
|
|
ads_total = []
|
|
|
|
|
if not ads["success"]:
|
|
|
|
|
return False
|
|
|
|
|
for ad in ads["response"]["data"]["ad_list"]:
|
|
|
|
|
for ad in ads["ad_list"]:
|
|
|
|
|
ads_total.append(ad["data"]["ad_id"])
|
|
|
|
|
if "pagination" in ads["response"]:
|
|
|
|
|
if "next" in ads["response"]["pagination"]:
|
|
|
|
|
if "pagination" in ads:
|
|
|
|
|
if ads["pagination"]:
|
|
|
|
|
if "next" in ads["pagination"]:
|
|
|
|
|
page += 1
|
|
|
|
|
ads_iter = await self.enum_ad_ids(page)
|
|
|
|
|
if ads_iter is None:
|
|
|
|
@ -271,32 +301,24 @@ class LocalPlatformClient(ABC):
|
|
|
|
|
return ads_total
|
|
|
|
|
|
|
|
|
|
async def enum_ads(self, requested_asset=None, page=0):
|
|
|
|
|
if self.name == "lbtc" and page == 0:
|
|
|
|
|
page = 1
|
|
|
|
|
query_values = {"page": page}
|
|
|
|
|
if requested_asset:
|
|
|
|
|
query_values["asset"] = requested_asset
|
|
|
|
|
# ads = await self.api._api_call(api_method="ads", query_values=query_values)
|
|
|
|
|
ads = await self.api.ads(page=page)
|
|
|
|
|
if ads is False:
|
|
|
|
|
return False
|
|
|
|
|
ads = await self.call("ads", page=page)
|
|
|
|
|
ads_total = []
|
|
|
|
|
if not ads["success"]:
|
|
|
|
|
return False
|
|
|
|
|
if not ads["response"]:
|
|
|
|
|
return False
|
|
|
|
|
for ad in ads["response"]["data"]["ad_list"]:
|
|
|
|
|
if self.name == "agora":
|
|
|
|
|
for ad in ads["ad_list"]:
|
|
|
|
|
asset = ad["data"]["asset"]
|
|
|
|
|
elif self.name == "lbtc":
|
|
|
|
|
asset = "BTC"
|
|
|
|
|
ad_id = ad["data"]["ad_id"]
|
|
|
|
|
country = ad["data"]["countrycode"]
|
|
|
|
|
currency = ad["data"]["currency"]
|
|
|
|
|
provider = ad["data"]["online_provider"]
|
|
|
|
|
ads_total.append([asset, ad_id, country, currency, provider])
|
|
|
|
|
if "pagination" in ads["response"]:
|
|
|
|
|
if "next" in ads["response"]["pagination"]:
|
|
|
|
|
if "pagination" in ads:
|
|
|
|
|
if ads["pagination"]:
|
|
|
|
|
if "next" in ads["pagination"]:
|
|
|
|
|
page += 1
|
|
|
|
|
ads_iter = await self.enum_ads(requested_asset, page)
|
|
|
|
|
if ads_iter is None:
|
|
|
|
@ -331,16 +353,8 @@ class LocalPlatformClient(ABC):
|
|
|
|
|
sec_ago_date = (now - date_parsed).total_seconds()
|
|
|
|
|
return sec_ago_date < 172800
|
|
|
|
|
|
|
|
|
|
async def enum_public_ads(self, asset, currency, providers=None, page=0):
|
|
|
|
|
if self.name == "lbtc" and page == 0:
|
|
|
|
|
page = 1
|
|
|
|
|
async def enum_public_ads(self, asset, currency, provider, page=0):
|
|
|
|
|
to_return = []
|
|
|
|
|
# if asset == "XMR":
|
|
|
|
|
# coin = "monero"
|
|
|
|
|
# elif asset == "BTC":
|
|
|
|
|
# coin = "bitcoins"
|
|
|
|
|
if not providers:
|
|
|
|
|
providers = ["NATIONAL_BANK"]
|
|
|
|
|
# buy-monero-online, buy-bitcoin-online
|
|
|
|
|
# Work around Agora weirdness calling it bitcoins
|
|
|
|
|
# ads = await self.api._api_call(
|
|
|
|
@ -348,28 +362,31 @@ class LocalPlatformClient(ABC):
|
|
|
|
|
# query_values={"page": page},
|
|
|
|
|
# )
|
|
|
|
|
if asset == "XMR":
|
|
|
|
|
ads = await self.api.buy_monero_online(currency_code=currency, page=page)
|
|
|
|
|
ads = await self.call(
|
|
|
|
|
"buy_monero_online",
|
|
|
|
|
currency_code=currency,
|
|
|
|
|
payment_method=provider,
|
|
|
|
|
page=page,
|
|
|
|
|
)
|
|
|
|
|
elif asset == "BTC":
|
|
|
|
|
ads = await self.api.buy_bitcoins_online(currency_code=currency, page=page)
|
|
|
|
|
# with open("pub.json", "a") as f:
|
|
|
|
|
# import json
|
|
|
|
|
# f.write(json.dumps([page, currency, asset, ads])+"\n")
|
|
|
|
|
# f.close()
|
|
|
|
|
if ads is None:
|
|
|
|
|
return False
|
|
|
|
|
if ads is False:
|
|
|
|
|
return False
|
|
|
|
|
if ads["response"] is None:
|
|
|
|
|
return False
|
|
|
|
|
if "data" not in ads["response"]:
|
|
|
|
|
ads = await self.call(
|
|
|
|
|
"buy_bitcoins_online",
|
|
|
|
|
currency_code=currency,
|
|
|
|
|
payment_method=provider,
|
|
|
|
|
page=page,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
raise Exception("Unknown asset")
|
|
|
|
|
if not ads["success"]:
|
|
|
|
|
return False
|
|
|
|
|
for ad in ads["response"]["data"]["ad_list"]:
|
|
|
|
|
provider = ad["data"]["online_provider"]
|
|
|
|
|
found_us = False
|
|
|
|
|
for ad in ads["ad_list"]:
|
|
|
|
|
provider_ad = ad["data"]["online_provider"]
|
|
|
|
|
if self.name == "lbtc":
|
|
|
|
|
provider_test = self.map_provider(provider)
|
|
|
|
|
provider_test = self.map_provider(provider_ad)
|
|
|
|
|
else:
|
|
|
|
|
provider_test = provider
|
|
|
|
|
if provider_test not in providers:
|
|
|
|
|
if provider_test != provider:
|
|
|
|
|
continue
|
|
|
|
|
date_last_seen = ad["data"]["profile"]["last_online"]
|
|
|
|
|
# Check if this person was seen recently
|
|
|
|
@ -377,17 +394,25 @@ class LocalPlatformClient(ABC):
|
|
|
|
|
continue
|
|
|
|
|
ad_id = str(ad["data"]["ad_id"])
|
|
|
|
|
username = ad["data"]["profile"]["username"]
|
|
|
|
|
if username == self.instance.username:
|
|
|
|
|
found_us = True
|
|
|
|
|
temp_price = ad["data"]["temp_price"]
|
|
|
|
|
if ad["data"]["currency"] != currency:
|
|
|
|
|
continue
|
|
|
|
|
to_append = [ad_id, username, temp_price, provider, asset, currency]
|
|
|
|
|
to_append = [ad_id, username, temp_price, provider_ad, asset, currency]
|
|
|
|
|
if to_append not in to_return:
|
|
|
|
|
to_return.append(to_append)
|
|
|
|
|
# await [ad_id, username, temp_price, provider, asset, currency]
|
|
|
|
|
if "pagination" in ads["response"]:
|
|
|
|
|
if "next" in ads["response"]["pagination"]:
|
|
|
|
|
|
|
|
|
|
if found_us:
|
|
|
|
|
return to_return
|
|
|
|
|
if "pagination" in ads:
|
|
|
|
|
if ads["pagination"]:
|
|
|
|
|
if "next" in ads["pagination"]:
|
|
|
|
|
page += 1
|
|
|
|
|
ads_iter = await self.enum_public_ads(asset, currency, providers, page)
|
|
|
|
|
ads_iter = await self.enum_public_ads(
|
|
|
|
|
asset, currency, provider, page
|
|
|
|
|
)
|
|
|
|
|
if ads_iter is None:
|
|
|
|
|
return False
|
|
|
|
|
if ads_iter is False:
|
|
|
|
@ -398,27 +423,7 @@ class LocalPlatformClient(ABC):
|
|
|
|
|
to_return.append(to_append)
|
|
|
|
|
return to_return
|
|
|
|
|
|
|
|
|
|
async def run_cheat_in_thread(self, assets=None):
|
|
|
|
|
"""
|
|
|
|
|
Update prices in another thread.
|
|
|
|
|
"""
|
|
|
|
|
if not assets:
|
|
|
|
|
all_assets = ["XMR"]
|
|
|
|
|
assets_not_run = set(all_assets) ^ set(self.cheat_run_on)
|
|
|
|
|
if not assets_not_run:
|
|
|
|
|
self.cheat_run_on = []
|
|
|
|
|
asset = list(all_assets).pop()
|
|
|
|
|
self.cheat_run_on.append(asset)
|
|
|
|
|
else:
|
|
|
|
|
asset = assets_not_run.pop()
|
|
|
|
|
self.cheat_run_on.append(asset)
|
|
|
|
|
await self.update_prices([asset])
|
|
|
|
|
return asset
|
|
|
|
|
else:
|
|
|
|
|
# deferToThread(self.update_prices, assets)
|
|
|
|
|
await self.update_prices(assets)
|
|
|
|
|
|
|
|
|
|
async def update_prices(self, assets=None):
|
|
|
|
|
async def cheat(self, assets=None):
|
|
|
|
|
# Get all public ads for the given assets
|
|
|
|
|
public_ads = await self.get_all_public_ads(assets)
|
|
|
|
|
if not public_ads:
|
|
|
|
@ -446,18 +451,20 @@ class LocalPlatformClient(ABC):
|
|
|
|
|
providers = providers or self.instance.ads_providers
|
|
|
|
|
currencies = currencies or self.instance.currencies
|
|
|
|
|
# We want to get the ads for each of these currencies and return the result
|
|
|
|
|
rates = await money.cg.get_price(
|
|
|
|
|
ids=["monero", "bitcoin"], vs_currencies=currencies
|
|
|
|
|
async with AsyncCoinGeckoAPISession() as cg:
|
|
|
|
|
rates = await cg.get_price(
|
|
|
|
|
ids="monero,bitcoin", vs_currencies=",".join(currencies)
|
|
|
|
|
)
|
|
|
|
|
for asset in assets:
|
|
|
|
|
for currency in currencies:
|
|
|
|
|
for provider in providers:
|
|
|
|
|
cg_asset_name = crypto_map[asset]
|
|
|
|
|
try:
|
|
|
|
|
rates[cg_asset_name][currency.lower()]
|
|
|
|
|
except KeyError:
|
|
|
|
|
log.debug(f"Error getting public ads for currency: {currency}")
|
|
|
|
|
continue
|
|
|
|
|
ads_list = await self.enum_public_ads(asset, currency, providers)
|
|
|
|
|
ads_list = await self.enum_public_ads(asset, currency, provider)
|
|
|
|
|
if not ads_list:
|
|
|
|
|
log.debug("Error getting ads list.")
|
|
|
|
|
continue
|
|
|
|
@ -466,7 +473,7 @@ class LocalPlatformClient(ABC):
|
|
|
|
|
log.debug("Error lookup up rates.")
|
|
|
|
|
continue
|
|
|
|
|
log.debug("Writing to ES.")
|
|
|
|
|
await self.write_to_es_ads("ads", ads)
|
|
|
|
|
# await self.write_to_es_ads("ads", ads)
|
|
|
|
|
if currency in public_ads:
|
|
|
|
|
for ad in list(ads):
|
|
|
|
|
if ad not in public_ads[currency]:
|
|
|
|
@ -980,7 +987,7 @@ class LocalPlatformClient(ABC):
|
|
|
|
|
|
|
|
|
|
# (asset, currency, provider)
|
|
|
|
|
assets = self.instance.ads_assets
|
|
|
|
|
currencies = self.currencies
|
|
|
|
|
currencies = self.instance.currencies
|
|
|
|
|
providers = self.instance.ads_providers
|
|
|
|
|
# if platform == "lbtc":
|
|
|
|
|
# providers = [
|
|
|
|
@ -1161,7 +1168,7 @@ class LocalPlatformClient(ABC):
|
|
|
|
|
currency_account_info_map[currency]["recipient"] = account[
|
|
|
|
|
"ownerName"
|
|
|
|
|
]
|
|
|
|
|
return (currencies, currency_account_info_map)
|
|
|
|
|
return (list(currency_account_info_map.keys()), currency_account_info_map)
|
|
|
|
|
|
|
|
|
|
def get_matching_account_details(self, currency, ad):
|
|
|
|
|
(
|
|
|
|
|