Heim > Backend-Entwicklung > Python-Tutorial > Ausführen eines Discord-Bots auf Raspberry Pi

Ausführen eines Discord-Bots auf Raspberry Pi

Susan Sarandon
Freigeben: 2024-10-01 12:11:02
Original
779 Leute haben es durchsucht

Titelbild von Daniel Tafjord auf Unsplash

Ich habe kürzlich ein Software-Engineering-Bootcamp abgeschlossen, mit der Arbeit an einfachen LeetCode-Fragen begonnen und hatte das Gefühl, dass es mir helfen würde, Verantwortung zu übernehmen, wenn ich täglich daran erinnert würde, Fragen zu lösen. Ich beschloss, dies mithilfe eines Discord-Bots zu implementieren, der im 24-Stunden-Rhythmus läuft (natürlich auf meinem treuen Raspberry Pi), der Folgendes tun würde:

  • Gehen Sie zu einer vordefinierten Datenbank mit einfachen Leetcode-Fragen
  • Ergreifen Sie eine Frage, die noch nicht im Discord-Kanal gepostet wurde
  • Posten Sie die Leetcode-Frage als Thread im Discord-Kanal (damit Sie Ihre Lösung einfach hinzufügen können)
  • Frage wird als gepostet markiert, um zu vermeiden, dass sie erneut im Kanal gepostet wird

Running a Discord Bot on Raspberry Pi

Mir ist klar, dass es vielleicht einfacher ist, einfach zu LeetCode zu gehen und täglich eine Frage zu lösen, aber ich habe bei diesem Miniprojekt mit Hilfe von ChatGPT viel über Python und Discord lernen können. Dies ist auch mein erster Versuch, Sketchnoting zu erstellen, also haben Sie bitte Geduld, lol

Running a Discord Bot on Raspberry Pi

Aufstellen

1. Verwenden Sie eine virtuelle Python-Umgebung
2. Abhängigkeiten installieren
3. Richten Sie die Leetcode-Datenbank für einfache Fragen ein
4. Umgebungsvariablen einrichten
5. Discord-App erstellen
6. Führen Sie den Bot aus!

1. Verwenden Sie eine virtuelle Python-Umgebung

Ich empfehle die Verwendung einer virtuellen Python-Umgebung, da ich beim ersten Test unter Ubuntu 24.04 auf den folgenden Fehler gestoßen bin

Running a Discord Bot on Raspberry Pi

Das Einrichten ist relativ einfach, führen Sie einfach die folgenden Befehle aus und voilà, Sie befinden sich in einer virtuellen Python-Umgebung!

1

2

3

python3 -m venv ~/py_envs

ls ~/py_envs  # to confirm the environment was created

source ~/py_envs/bin/activate

Nach dem Login kopieren

2. Abhängigkeiten installieren

Die folgenden Abhängigkeiten sind erforderlich:

  • AWS CLI

Installieren Sie AWS CLI, indem Sie Folgendes ausführen:

1

2

3

4

curl -O 'https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip'

unzip awscli-exe-linux-aarch64.zip

sudo ./aws/install

aws --version

Nach dem Login kopieren

Führen Sie dann aws configure aus, um die erforderlichen Anmeldeinformationen hinzuzufügen. Siehe Konfigurieren des AWS CLI-Dokuments.

  • Pip-Abhängigkeiten

Die folgenden Pip-Abhängigkeiten können mit einer Anforderungsdatei installiert werden, indem pip install -r require.txt ausgeführt wird.

1

2

3

4

5

6

7

8

# requirements.txt

 

discord.py

# must install this version of numpy to prevent conflict with

# pandas, both of which are required by leetscrape

numpy==1.26.4  

leetscrape

python-dotenv

Nach dem Login kopieren

3. Richten Sie die Leetcode-Datenbank für einfache Fragen ein

Leetscrape war für diesen Schritt von entscheidender Bedeutung. Weitere Informationen dazu finden Sie in den Leetscrape-Dokumenten.
Ich möchte nur an einfachen Leetcode-Fragen arbeiten (für mich sind sie sogar ziemlich schwierig), also habe ich Folgendes getan:

  • Erhalten Sie die Liste aller Fragen von Leetcode mit Leetscrape und speichern Sie die Liste im CSV-Format

1

2

3

4

5

6

from leetscrape import GetQuestionsList

 

ls = GetQuestionsList()

ls.scrape() # Scrape the list of questions

ls.questions.head() # Get the list of questions

ls.to_csv(directory="path/to/csv/file")

Nach dem Login kopieren
  • Erstellen Sie eine Amazon DynamoDB-Tabelle und füllen Sie sie mit einer Liste einfacher Fragen, die aus der im vorherigen Schritt gespeicherten CSV-Datei gefiltert wurden.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

import csv

import boto3

from botocore.exceptions import BotoCoreError, ClientError

 

# Initialize the DynamoDB client

dynamodb = boto3.resource('dynamodb')

 

def filter_and_format_csv_for_dynamodb(input_csv):

    result = []

 

    with open(input_csv, mode='r') as file:

        csv_reader = csv.DictReader(file)

 

        for row in csv_reader:

            # Filter based on difficulty and paidOnly fields

            if row['difficulty'] == 'Easy' and row['paidOnly'] == 'False':

                item = {

                    'QID': {'N': str(row['QID'])}, 

                    'titleSlug': {'S': row['titleSlug']},

                    'topicTags': {'S': row['topicTags']}, 

                    'categorySlug': {'S': row['categorySlug']}, 

                    'posted': {'BOOL': False} 

                }

                result.append(item)

 

    return result

 

def upload_to_dynamodb(items, table_name):

    table = dynamodb.Table(table_name)

 

    try:

        with table.batch_writer() as batch:

            for item in items:

                batch.put_item(Item={

                    'QID': int(item['QID']['N']), 

                    'titleSlug': item['titleSlug']['S'],

                    'topicTags': item['topicTags']['S'],

                    'categorySlug': item['categorySlug']['S'],

                    'posted': item['posted']['BOOL']

                })

        print(f"Data uploaded successfully to {table_name}")

 

    except (BotoCoreError, ClientError) as error:

        print(f"Error uploading data to DynamoDB: {error}")

 

def create_table():

    try:

        table = dynamodb.create_table(

            TableName='leetcode-easy-qs',

            KeySchema=[

                {

                    'AttributeName': 'QID',

                    'KeyType': 'HASH'  # Partition key

                }

            ],

            AttributeDefinitions=[

                {

                    'AttributeName': 'QID',

                    'AttributeType': 'N'  # Number type

                }

            ],

            ProvisionedThroughput={

                'ReadCapacityUnits': 5,

                'WriteCapacityUnits': 5

            }

        )

 

        # Wait until the table exists

        table.meta.client.get_waiter('table_exists').wait(TableName='leetcode-easy-qs')

        print(f"Table {table.table_name} created successfully!")

 

    except Exception as e:

        print(f"Error creating table: {e}")

 

# Call function to create the table

create_table()

 

# Example usage

input_csv = 'getql.pyquestions.csv'  # Your input CSV file

table_name = 'leetcode-easy-qs'      # DynamoDB table name

 

# Step 1: Filter and format the CSV data

questions = filter_and_format_csv_for_dynamodb(input_csv)

 

# Step 2: Upload data to DynamoDB

upload_to_dynamodb(questions, table_name)

Nach dem Login kopieren

4. Umgebungsvariablen einrichten

Erstellen Sie eine .env-Datei zum Speichern von Umgebungsvariablen

1

DISCORD_BOT_TOKEN=*****

Nach dem Login kopieren

5. Erstellen Sie eine Discord-App

Befolgen Sie die Anweisungen in den Discord-Entwicklerdokumenten, um eine Discord-App und einen Discord-Bot mit entsprechenden Berechtigungen zu erstellen. Stellen Sie sicher, dass Sie den Bot mit mindestens den folgenden OAuth-Berechtigungen autorisieren:

  • Nachrichten senden
  • Öffentliche Threads erstellen
  • Nachrichten in Threads senden

6. Führen Sie den Bot aus!

Unten finden Sie den Code für den Bot, der mit dem Befehl python3 discord-leetcode-qs.py ausgeführt werden kann.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

import os

import discord

import boto3

from leetscrape import GetQuestion

from discord.ext import tasks

from dotenv import load_dotenv

import re

load_dotenv()

 

# Discord bot token

TOKEN = os.getenv('DISCORD_TOKEN')

 

# Set the intents for the bot

intents = discord.Intents.default()

intents.message_content = True # Ensure the bot can read messages

 

# Initialize the bot

bot = discord.Client(intents=intents)

# DynamoDB setup

dynamodb = boto3.client('dynamodb')

 

TABLE_NAME = 'leetcode-easy-qs'

CHANNEL_ID = 1211111111111111111  # Replace with the actual channel ID

 

# Function to get the first unposted item from DynamoDB

def get_unposted_item():

    response = dynamodb.scan(

        TableName=TABLE_NAME,

        FilterExpression='posted = :val',

        ExpressionAttributeValues={':val': {'BOOL': False}},

    )

    items = response.get('Items', [])

    if items:

        return items[0]

    return None

 

# Function to mark the item as posted in DynamoDB

def mark_as_posted(qid):

    dynamodb.update_item(

        TableName=TABLE_NAME,

        Key={'QID': {'N': str(qid)}},

        UpdateExpression='SET posted = :val',

        ExpressionAttributeValues={':val': {'BOOL': True}}

    )

 

MAX_MESSAGE_LENGTH = 2000

AUTO_ARCHIVE_DURATION = 2880

 

# Function to split a question into words by spaces or newlines

def split_question(question, max_length):

    parts = []

    while len(question) > max_length:

        split_at = question.rfind(' ', 0, max_length)

        if split_at == -1:

            split_at = question.rfind('\n', 0, max_length)

        if split_at == -1:

            split_at = max_length

 

        parts.append(question[:split_at].strip())

        # Continue with the remaining text

        question = question[split_at:].strip()

 

    if question:

        parts.append(question)

 

    return parts

 

def clean_question(question):

    first_line, _, remaining_question = message.partition('\n')

    return re.sub(r'\n{3,}', '\n', remaining_question)

 

def extract_first_line(question):

    lines = question.splitlines()

    return lines[0] if lines else ""

 

# Task that runs on a schedule

@tasks.loop(minutes=1440)

async def scheduled_task():

    channel = bot.get_channel(CHANNEL_ID)

    item = get_unposted_item()

 

    if item:

        title_slug = item['titleSlug']['S']

        qid = item['QID']['N']

        question = "%s" % (GetQuestion(titleSlug=title_slug).scrape())

 

        first_line = extract_first_line(question)

        cleaned_question = clean_message(question)

        parts = split_message(cleaned_question, MAX_MESSAGE_LENGTH)

 

        thread = await channel.create_thread(

            name=first_line,

            type=discord.ChannelType.public_thread

        )

 

        for part in parts:

            await thread.send(part)

 

        mark_as_posted(qid)

    else:

        print("No unposted items found.")

 

@bot.event

async def on_ready():

    print(f'{bot.user} has connected to Discord!')

    scheduled_task.start()

 

@bot.event

async def on_thread_create(thread):

    await thread.send("\nYour challenge starts here! Good Luck!")

 

# Run the bot

bot.run(TOKEN)

Nach dem Login kopieren

Es gibt mehrere Möglichkeiten, den Bot auszuführen. Im Moment führe ich das nur in einer tmux-Shell aus, aber Sie könnten es auch in einem Docker-Container oder auf einer VPC von AWS, Azure, DigitalOcean oder anderen Cloud-Anbietern ausführen.

Jetzt muss ich nur noch versuchen, die Leetcode-Fragen zu lösen...

Das obige ist der detaillierte Inhalt vonAusführen eines Discord-Bots auf Raspberry Pi. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage