Libraries refactor and add some sinks #4

Closed
m wants to merge 136 commits from library-refactor into master
7 changed files with 114 additions and 182 deletions
Showing only changes of commit 4fe315cf91 - Show all commits

View File

@ -64,15 +64,6 @@ class Agora(object):
# Assets that cheat has been run on # Assets that cheat has been run on
self.cheat_run_on = [] self.cheat_run_on = []
def set_irc(self, irc):
self.irc = irc
def set_tx(self, tx):
self.tx = tx
def set_notify(self, notify):
self.notify = notify
def setup_loop(self): def setup_loop(self):
""" """
Set up the LoopingCall to get all active trades and messages. Set up the LoopingCall to get all active trades and messages.
@ -475,11 +466,11 @@ class Agora(object):
continue continue
if xmr: if xmr:
if asset == "XMR": if asset == "XMR":
new_margin = self.autoprice(public_ads, currency) new_margin = self.markets.autoprice(public_ads, currency)
new_formula = f"coingeckoxmrusd*usd{currency.lower()}*{new_margin}" new_formula = f"coingeckoxmrusd*usd{currency.lower()}*{new_margin}"
if btc: if btc:
if asset == "BTC": if asset == "BTC":
new_margin = self.autoprice(public_ads, currency) new_margin = self.markets.autoprice(public_ads, currency)
new_formula = f"coingeckobtcusd*usd{currency.lower()}*{new_margin}" new_formula = f"coingeckobtcusd*usd{currency.lower()}*{new_margin}"
# Get all of our ads # Get all of our ads
our_ads_list = [ad for ad in public_ads if ad[1] == settings.Agora.Username] our_ads_list = [ad for ad in public_ads if ad[1] == settings.Agora.Username]
@ -556,79 +547,6 @@ class Agora(object):
) )
self.irc.sendmsg(f"Slow ad update completed with {iterations} iterations: [{', '.join(assets)}] | [{', '.join(currencies)}]") self.irc.sendmsg(f"Slow ad update completed with {iterations} iterations: [{', '.join(assets)}] | [{', '.join(currencies)}]")
def autoprice(self, ads, currency):
"""
Helper function to automatically adjust the price up/down in certain markets
in order to gain the most profits and sales.
:param ads: list of ads
:type ads: list of lists
:param currency: currency of the ads
:type currency: string
:return: the rate we should use for this currency
:rtype: float
"""
self.log.debug("Autoprice starting for {x}", x=currency)
# Find cheapest ad
# Filter by 3rd index on each ad list to find the cheapest
min_margin_ad = min(ads, key=lambda x: x[4])
self.log.debug("Minimum margin ad: {x}", x=min_margin_ad)
# Find second cheapest that is not us
# Remove results from ads that are us
ads_without_us = [ad for ad in ads if not ad[1] == settings.Agora.Username]
self.log.debug("Ads without us: {x}", x=ads_without_us)
# Find ads above our min that are not us
ads_above_our_min_not_us = [ad for ad in ads_without_us if ad[4] > float(settings.Agora.MinMargin)]
self.log.debug("Ads above our min not us: {x}", x=ads_above_our_min_not_us)
# Check that this list without us is not empty
if ads_without_us:
# Find the cheapest from these
min_margin_ad_not_us = min(ads_without_us, key=lambda x: x[4])
self.log.debug("Min margin ad not us: {x}", x=min_margin_ad_not_us)
# Lowball the lowest ad that is not ours
lowball_lowest_not_ours = min_margin_ad_not_us[4] # - 0.005
self.log.debug("Lowball lowest not ours: {x}", x=lowball_lowest_not_ours)
# Check if the username field of the cheapest ad matches ours
if min_margin_ad[1] == settings.Agora.Username:
self.log.debug("We are the cheapest for: {x}", x=currency)
# We are the cheapest!
# Are all of the ads ours?
all_ads_ours = all([ad[1] == settings.Agora.Username for ad in ads])
if all_ads_ours:
self.log.debug("All ads are ours for: {x}", x=currency)
# Now we know it's safe to return the maximum value
return float(settings.Agora.MaxMargin)
else:
self.log.debug("All ads are NOT ours for: {x}", x=currency)
# All the ads are not ours, but we are first...
# Check if the lowballed, lowest (that is not ours) ad's margin
# is less than our minimum
if lowball_lowest_not_ours < float(settings.Agora.MinMargin):
self.log.debug("Lowball lowest not ours less than MinMargin")
return float(settings.Agora.MinMargin)
elif lowball_lowest_not_ours > float(settings.Agora.MaxMargin):
self.log.debug("Lowball lowest not ours more than MaxMargin")
return float(settings.Agora.MaxMargin)
else:
self.log.debug("Returning lowballed figure: {x}", x=lowball_lowest_not_ours)
return lowball_lowest_not_ours
else:
self.log.debug("We are NOT the cheapest for: {x}", x=currency)
# We are not the cheapest :(
# Check if this list is empty
if not ads_above_our_min_not_us:
# Return the maximum margin?
return float(settings.Agora.MaxMargin)
# Find cheapest ad above our min that is not us
cheapest_ad = min(ads_above_our_min_not_us, key=lambda x: x[4])
cheapest_ad_margin = cheapest_ad[4] # - 0.005
if cheapest_ad_margin > float(settings.Agora.MaxMargin):
self.log.debug("Cheapest ad not ours more than MaxMargin")
return float(settings.Agora.MaxMargin)
self.log.debug("Cheapest ad above our min that is not us: {x}", x=cheapest_ad)
return cheapest_ad_margin
@handle_exceptions @handle_exceptions
def nuke_ads(self): def nuke_ads(self):
""" """

View File

@ -16,6 +16,7 @@ from agora import Agora
from transactions import Transactions from transactions import Transactions
from irc import bot from irc import bot
from notify import Notify from notify import Notify
from markets import Markets
def convert(data): def convert(data):
@ -38,9 +39,6 @@ class WebApp(object):
def __init__(self): def __init__(self):
self.log = Logger("webapp") self.log = Logger("webapp")
def set_tx(self, tx):
self.tx = tx
@app.route("/callback", methods=["POST"]) @app.route("/callback", methods=["POST"])
def callback(self, request): def callback(self, request):
content = request.content.read() content = request.content.read()
@ -55,59 +53,33 @@ class WebApp(object):
if __name__ == "__main__": if __name__ == "__main__":
# Define Notify init_map = {
notify = Notify() "notify": Notify(),
"irc": bot(),
"agora": Agora(),
"markets": Markets(),
"revolut": Revolut(),
"tx": Transactions(),
"webapp": WebApp(),
}
for classname, object_instance in init_map.items():
# notify, Notify
for classname_inside, object_instance_inside in init_map.items():
if not classname == classname_inside:
# irc, bot
setattr(object_instance, classname_inside, object_instance_inside)
# Define IRC and Agora
irc = bot()
agora = Agora()
# Pass Notify to IRC and Agora
irc.set_notify(notify)
agora.set_notify(notify)
# Pass Agora to Notify
notify.set_agora(agora)
# Pass IRC to Agora and Agora to IRC
# This is to prevent recursive dependencies
agora.set_irc(irc)
irc.set_agora(agora)
# Define Revolut
revolut = Revolut()
# Pass IRC to Revolut and Revolut to IRC
revolut.set_irc(irc)
irc.set_revolut(revolut)
revolut.set_agora(agora)
# Define Transactions
tx = Transactions()
# Pass Notify to Transactions
tx.set_notify(notify)
# Pass Agora and IRC to Transactions and Transactions to IRC
tx.set_agora(agora)
tx.set_irc(irc)
tx.set_revolut(revolut)
irc.set_tx(tx)
agora.set_tx(tx)
# Define WebApp
webapp = WebApp()
webapp.set_tx(tx)
# Handle setting up JWT and request_token from an auth code # Handle setting up JWT and request_token from an auth code
if settings.Revolut.SetupToken == "1": if settings.Revolut.SetupToken == "1":
deferLater(reactor, 1, revolut.setup_auth) deferLater(reactor, 1, init_map["revolut"].setup_auth)
else: else:
# Schedule refreshing the access token using the refresh token # Schedule refreshing the access token using the refresh token
deferLater(reactor, 1, revolut.get_new_token, True) deferLater(reactor, 1, init_map["revolut"].get_new_token, True)
# Check if the webhook is set up and set up if not # Check if the webhook is set up and set up if not
deferLater(reactor, 4, revolut.setup_webhook) deferLater(reactor, 4, init_map["revolut"].setup_webhook)
# Schedule repeatedly refreshing the access token # Schedule repeatedly refreshing the access token
lc = LoopingCall(revolut.get_new_token) lc = LoopingCall(init_map["revolut"].get_new_token)
lc.start(int(settings.Revolut.RefreshSec)) lc.start(int(settings.Revolut.RefreshSec))
# Run the WebApp # Run the WebApp
webapp.app.run("127.0.0.1", 8080) init_map["webapp"].app.run("127.0.0.1", 8080)

View File

@ -38,18 +38,6 @@ class IRCBot(irc.IRCClient):
self.channel = settings.IRC.Channel self.channel = settings.IRC.Channel
def set_agora(self, agora):
self.agora = agora
def set_revolut(self, revolut):
self.revolut = revolut
def set_tx(self, tx):
self.tx = tx
def set_notify(self, notify):
self.notify = notify
def parse(self, user, host, channel, msg): def parse(self, user, host, channel, msg):
""" """
Simple handler for IRC commands. Simple handler for IRC commands.
@ -185,18 +173,6 @@ class IRCBotFactory(protocol.ClientFactory):
def __init__(self): def __init__(self):
self.log = Logger("irc") self.log = Logger("irc")
def set_agora(self, agora):
self.agora = agora
def set_revolut(self, revolut):
self.revolut = revolut
def set_tx(self, tx):
self.tx = tx
def set_notify(self, notify):
self.notify = notify
def sendmsg(self, msg): def sendmsg(self, msg):
""" """
Passthrough function to send a message to the channel. Passthrough function to send a message to the channel.
@ -215,10 +191,10 @@ class IRCBotFactory(protocol.ClientFactory):
""" """
prcol = IRCBot(self.log) prcol = IRCBot(self.log)
self.client = prcol self.client = prcol
self.client.set_agora(self.agora) setattr(self.client, "agora", self.agora)
self.client.set_revolut(self.revolut) setattr(self.client, "revolut", self.revolut)
self.client.set_tx(self.tx) setattr(self.client, "tx", self.tx)
self.client.set_notify(self.notify) setattr(self.client, "notify", self.notify)
return prcol return prcol
def clientConnectionLost(self, connector, reason): def clientConnectionLost(self, connector, reason):

87
handler/markets.py Normal file
View File

@ -0,0 +1,87 @@
# Twisted/Klein imports
from twisted.logger import Logger
# Project imports
from settings import settings
class Markets(object):
""" "
Markets handler for generic market functions.
"""
def __init__(self):
self.log = Logger("markets")
def autoprice(self, ads, currency):
"""
Helper function to automatically adjust the price up/down in certain markets
in order to gain the most profits and sales.
:param ads: list of ads
:type ads: list of lists
:param currency: currency of the ads
:type currency: string
:return: the rate we should use for this currency
:rtype: float
"""
self.log.debug("Autoprice starting for {x}", x=currency)
# Find cheapest ad
# Filter by 3rd index on each ad list to find the cheapest
min_margin_ad = min(ads, key=lambda x: x[4])
self.log.debug("Minimum margin ad: {x}", x=min_margin_ad)
# Find second cheapest that is not us
# Remove results from ads that are us
ads_without_us = [ad for ad in ads if not ad[1] == settings.Agora.Username]
self.log.debug("Ads without us: {x}", x=ads_without_us)
# Find ads above our min that are not us
ads_above_our_min_not_us = [ad for ad in ads_without_us if ad[4] > float(settings.Agora.MinMargin)]
self.log.debug("Ads above our min not us: {x}", x=ads_above_our_min_not_us)
# Check that this list without us is not empty
if ads_without_us:
# Find the cheapest from these
min_margin_ad_not_us = min(ads_without_us, key=lambda x: x[4])
self.log.debug("Min margin ad not us: {x}", x=min_margin_ad_not_us)
# Lowball the lowest ad that is not ours
lowball_lowest_not_ours = min_margin_ad_not_us[4] # - 0.005
self.log.debug("Lowball lowest not ours: {x}", x=lowball_lowest_not_ours)
# Check if the username field of the cheapest ad matches ours
if min_margin_ad[1] == settings.Agora.Username:
self.log.debug("We are the cheapest for: {x}", x=currency)
# We are the cheapest!
# Are all of the ads ours?
all_ads_ours = all([ad[1] == settings.Agora.Username for ad in ads])
if all_ads_ours:
self.log.debug("All ads are ours for: {x}", x=currency)
# Now we know it's safe to return the maximum value
return float(settings.Agora.MaxMargin)
else:
self.log.debug("All ads are NOT ours for: {x}", x=currency)
# All the ads are not ours, but we are first...
# Check if the lowballed, lowest (that is not ours) ad's margin
# is less than our minimum
if lowball_lowest_not_ours < float(settings.Agora.MinMargin):
self.log.debug("Lowball lowest not ours less than MinMargin")
return float(settings.Agora.MinMargin)
elif lowball_lowest_not_ours > float(settings.Agora.MaxMargin):
self.log.debug("Lowball lowest not ours more than MaxMargin")
return float(settings.Agora.MaxMargin)
else:
self.log.debug("Returning lowballed figure: {x}", x=lowball_lowest_not_ours)
return lowball_lowest_not_ours
else:
self.log.debug("We are NOT the cheapest for: {x}", x=currency)
# We are not the cheapest :(
# Check if this list is empty
if not ads_above_our_min_not_us:
# Return the maximum margin?
return float(settings.Agora.MaxMargin)
# Find cheapest ad above our min that is not us
cheapest_ad = min(ads_above_our_min_not_us, key=lambda x: x[4])
cheapest_ad_margin = cheapest_ad[4] # - 0.005
if cheapest_ad_margin > float(settings.Agora.MaxMargin):
self.log.debug("Cheapest ad not ours more than MaxMargin")
return float(settings.Agora.MaxMargin)
self.log.debug("Cheapest ad above our min that is not us: {x}", x=cheapest_ad)
return cheapest_ad_margin

View File

@ -16,9 +16,6 @@ class Notify(object):
def __init__(self): def __init__(self):
self.log = Logger("notify") self.log = Logger("notify")
def set_agora(self, agora):
self.agora = agora
def sendmsg(self, msg, title=None, priority=None, tags=None): def sendmsg(self, msg, title=None, priority=None, tags=None):
headers = {"Title": "Bot"} headers = {"Title": "Bot"}
if title: if title:

View File

@ -28,12 +28,6 @@ class Revolut(object):
self.log = Logger("revolut") self.log = Logger("revolut")
self.token = None self.token = None
def set_irc(self, irc):
self.irc = irc
def set_agora(self, agora):
self.agora = agora
def setup_auth(self): def setup_auth(self):
""" """
Function to create a new Java Web Token and use it to get a refresh/access token. Function to create a new Java Web Token and use it to get a refresh/access token.

View File

@ -24,18 +24,6 @@ class Transactions(object):
""" """
self.log = Logger("transactions") self.log = Logger("transactions")
def set_agora(self, agora):
self.agora = agora
def set_irc(self, irc):
self.irc = irc
def set_revolut(self, revolut):
self.revolut = revolut
def set_notify(self, notify):
self.notify = notify
def transaction(self, data): def transaction(self, data):
""" """
Store details of transaction and post notifications to IRC. Store details of transaction and post notifications to IRC.