1. Experiment 1: [Discord Bot]¶
Datum: [04.04.2024] Thema: [Discord Bot (Finanz Features)]
1.1. Einleitung¶
Discord übernimmt eine wichtige Rolle der Kommunikation, vor allem bei Jugendlichen. Sowohl für private Zwecke als auch in z.B. Servern vom Studiengang, in dem man Informationen und digitale Treffen veranstalten kann. Wenn man mal auf einem Discord Server war, sieht man viele verschiedene Bots, welche die unterschiedlichsten Funktionen und Aufgaben haben können. Und als angehender Informatiker fragt man sich da, wie schwer es ist, einen eigenen solchen Bot zu schreiben. So wurde die Entscheidung gefällt: Wir wollen uns an genau solch einen Bot wagen.
1.1.1. Motivation¶
Mit der Entscheidung getroffen, war jetzt die Frage, was für eine Funktionalität unser Bot haben soll. Da wir alle Interesse an Finanzen, dem Aktienmarkt und Kryptowährungen haben, haben wir uns entschieden, einen Bot zu schreiben, der in diesem Bereich einige Informationen für uns auf Anfrage anzeigen kann. So konnten wir auch neben dem Schreiben eines Bots auch lernen, welche Möglichkeiten wir haben, an solche Informationen kommen zu können.
1.1.2. Aufgabenstellung¶
Zuerst muss ein Discord Bot erstellt werden, mit dem wir dann theoretisch machen können, was wir wollen. Da wir aktuelle Informationen wollen, müssen wir APIs und oder verschiedene Python-Bibliotheken nutzen, die dann auf Anfrage aktuelle Informationen liefern. Wenn der Bot dann funktioniert, wird noch eine Installationsanweisung in der README.md verfasst.
1.2. Grundlagen¶
Wir verwenden für diesen Versuch Discord Tools für das Erstellen eines Bots und Python, um die Funktionalität unseres Bots zu implementieren. Auf der Developer Documentation von Discord wird Schritt für Schritt erklärt, wie ein Bot eingerichtet werden kann. Für Python verwenden wir die Version 3.12 und ein wenig asynchrone Programmierung, da Discord Bots asynchron arbeiten.
1.3. Versuchsdurchführung¶
Dieser Abschnitt beschreibt die Vorbereitung, Durchführung, erzielten Ergebnisse und eventuelle Probleme während des Versuchs. Als erstes, mussten wir herausfinden, wie man im Allgemeinen einen Discord Bot erstellt und so einrichtet, dass man ihn auf einen Server einladen kann. Dazu haben wir uns in die Developer Documentation von Discord einlesen müssen. Nachdem eine App registriert wurde, kann in dieser App ein Bot eingerichtet werden. Dieser Bot kann dann auf jeden beliebigen Server eingeladen werden und muss hierbei mit den richtigen Berechtigungen ausgestattet werden. Für den Versuch haben wir einen Discord Server erstellt, auf dem der Bot dann eingeladen wurde. Da all dies mit den Tools von Discord funktioniert, muss man nicht mehr machen erstmal.
Wenn man mit Discord Bots in Python arbeiten will, muss ein hinterlegtes Token im Bot immer präsent sein im Code, damit der Bot funktioniert. Dies geschieht bei uns so:
# Load the token from env
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
Wir haben uns dafür entschieden, den Token aus Sicherheitsgründen als Environment-Variable zu hinterlegen und dann in den Code zu laden. Unser Bot muss dann erstmal noch fähig gemacht werden, auf Interaktionen zu reagieren. Da Discord Bots asynchron arbeiten, geht dies in Python wie folgt:
# Bot message received
@client.event
async def on_message(message):
Mit der Deklaration „async“ wird in Python eine asynchrone Methode geschrieben. Die Methode „on_message“ prüft, wer der Eigentümer der Nachricht ist und falls es nicht der Bot ist, so macht sich der Bot bereit, dem Nachrichtensender eine Antwort zu geben. Die Antwort erfolgt dann durch die folgende Methode:
# Handle sending of messages
async def send_message(message, user_message):
In der Methode „send_message“ wird eine gesendete Nachricht darauf überprüft, ob sie der von uns erzwungenen Syntax entspricht. Sie muss mit einem „?“ beginnen und dann einen Befehl enthalten (mehr dazu im nächsten Code-Block). Wenn diese Anforderung erfüllt wird, wird unsere nachstehende Methode „get_response“ ausgeführt:
def get_response(user_input: str) -> str:
command = user_input.lower()
if command.startswith("convert"):
try:
parts = command.split()[1:] # Split the command into parts
amount = float(parts[0]) # Extract the amount to convert
from_currency = parts[1].upper() # Extract the source currency
to_currency = parts[-1].upper() # Extract the target currency
return convert_currency(amount, from_currency, to_currency)
except Exception as e:
print(e)
return f"Invalid command. Use `{PREFIX}help`."
elif command.startswith("currencies"):
return "**Supported currencies:**\n> " + "\n> ".join(get_supported_currencies())
elif command.startswith("stock"):
try:
parts = command.split()[1:] # Split the command into parts
stock_name = parts[0] # Extract the stock name
if len(parts) > 1:
duration = parts[1] # Extract the duration if provided
return get_stock_price_historic(stock_name, duration)
else:
return get_stock_price(stock_name)
except Exception as e:
print(e)
return f"Invalid command. Use `{PREFIX}help`. Or check for stock names on <https://stockanalysis.com/stocks/>"
elif command.startswith("crypto"):
try:
parts = command.split()[1:] # Split the command into parts
crypto_name = parts[0] # Extract the cryptocurrency name
return get_crypto_price(crypto_name)
except Exception as e:
print(e)
return f"Invalid command. Use `{PREFIX}help`."
elif command.startswith("help"):
return (f"Use `{PREFIX}convert <AMOUNT> <CURRENCY> to <TARGET_CURRENCY>`."
f"\nExample: `{PREFIX}convert 1 EUR to USD`"
f"\n\nUse `{PREFIX}currencies` to see the supported currencies."
f"\n\nUse `{PREFIX}stock <NAME>` to see the current or historic stock price."
f"\nList of stock names can be found on: <https://stockanalysis.com/stocks/>"
f"\nExample: `{PREFIX}stock AAPL`"
f"\nExample: `{PREFIX}stock NVDA 1y`"
f"\nAllowed durations: 1d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max"
f"\n\nUse `{PREFIX}crypto <CRYPTO_NAME>` to see the current cryptocurrency price."
f"\nExample: `{PREFIX}crypto Bitcoin`")
else:
return f"Invalid command. Use `{PREFIX}help`."
In dieser Methode sind alle unsere relevanten Bot-Kommandos ersichtlich. Bei der Eingabe „?help“ wird die Usage des Bots erklärt. Wenn das Kommando convert benutzt wird, kann eine Währung zu einer anderen mit einer beliebigen Menge umgerechnet werden. Das Kommando currencies zeigt alle verfügbaren Währungen an und bei stock kann der Wert eines Stocks über einen Zeitraum betrachtet werden. Das Kommando crypto gibt den aktuellen Wert einer beliebigen Kryptowährung zurück. Die einzelnen Methoden, die bei den Kommandos referenziert werden, nutzen alle entweder Python-Bibliotheken, oder APIs, um die Informationen aktuell zu erhalten. Bei den Krypto-Währungen sieht das beispielsweise dann so aus:
# Returns the current price of the cryptocurrency
def get_crypto_price(crypto_name):
response = requests.get(f'https://api.coingecko.com/api/v3/simple/price?ids={crypto_name}&vs_currencies=usd')
#[...]
Mit diesen paar Methoden ist unser Discord Bot dann bereits vollständig funktionsfähig. Der Bot muss dann einfach nur aktiviert werden, was auch wieder mit einer asynchronen Methode gehandhabt wird:
# Bot startup
@client.event
async def on_ready():
print(f"{client.user} is now running!")
def main():
client.run(TOKEN)
if __name__ == "__main__":
main()
Auf dem Discord-Server kann dann einfach jede Person die Kommandos eingeben und solange der Bot aktiv ist, gibt er die entsprechenden Antworten.
1.3.1. Ergebnisse¶
Der Bot funktioniert einwandfrei und interagiert gut mit den von uns bereitgestellten Methoden, da bei Falscheingaben entsprechende Exceptions im Code hinterlegt wurden. Die meiste Funktionalität haben wir auf die APIs und Bibliotheken ausgelagert, wodurch wir weniger Fehlerquellen unsererseits haben.
1.3.2. Fazit¶
Wir konnten alles umsetzen, was wir uns für Versuch 1 vorgenommen haben. Durch das sehr dokumentierte Developer-Portal von Discord ist das Erstellen des Bots nicht zu umständlich. Das Schreiben der Python Methoden wurde durch das Zurückgreifen auf APIs und Bibliotheken machbar. Wir müssen uns allerdings bewusst sein, dass wir durch die Hohe Konzentration an APIs und Bibliotheken einerseits potenzielle Sicherheitsrisiken haben und andererseits der Bot aktiv gewartet werden muss, um sicherzustellen, dass der API-Anbieter oder die Bibliothek noch aktiv weitergeführt wird. Dies ist in Anbetracht des Aufwands allerdings tragbar.
1.4. Literaturangaben¶
[1] https://discord.com/developers/docs/tutorials/developing-a-user-installable-app
[2] https://pypi.org/project/yfinance/
[3] https://forex-python.readthedocs.io/en/latest/index.html
[4] https://docs.coingecko.com/docs/1-get-data-by-id-or-address#a-coin-id