Command cooldown?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
homelessJames

Hallo,
ich habe erst vor kurzem angefangen mit Python zu programieren. Aber, dass was ich derzeit geschaft habe, kann man nicht wirklich programieren nennen. Wie auch immer...
Ich habe also einen Telegrambot, der mir den Stundenplan und die Hausaufgaben in einer Klassengruppe sendet. Ich hätte jetzt aber sehr gerne einen Cooldown [z.b. 5min], damit der Command nicht in einer Gruppe gespammt werden kann.
Die Texte/Nachrichten liegen bewusst in einer .txt, damit ich sie auch von meinem Handy z.b. in der Bahn auf meinem Raspberry Pi bearbeiten kann, ohne, dass ich den Bot umständlich Neustarten muss.

Code: Alles auswählen

# -*- coding: utf-8 -*-
import time
import random
import datetime
import telepot
from time import sleep

def handle(msg):
    chat_id = msg['chat']['id']
    command = msg['text']


    if 'Montag' in command or 'montag' in command or command == 'Mo' or command == 'mo':
        file = open("/home/pi/bots/Schulbot/Montag.txt")
        bot.sendMessage(chat_id, text=file.read())
        

bot = telepot.Bot('Geheimer Token.')
bot.message_loop(handle)
print 'Schulbot gestartet.'

while 1:
    time.sleep(10)
- Ein kleiner Ausschnitt von dem Script. Die anderen Commands sind ähnlich aufgebaut.
LG
Zuletzt geändert von homelessJames am Sonntag 25. September 2016, 16:29, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@homelessJames: Du müßtest Dir die Zeit merken, zu der die letzte Abfrage abgesetzt wurde (time.time) und alles Anfragen ignorieren, die innerhalb Deiner gewünschten Zeitspanne auftreten.
BlackJack

@homelessJames: Du müsstest Dir merken wann die letzte Ausgabe war und ausrechnen ob die schon länger als 5 Minuten zurück liegt. Dazu eignen sich die Datentypen aus dem `datetime`-Modul.

Um das sauber zu lösen brauchst Du eine Klasse. Brauchst Du im Grunde auch jetzt schon, denn das `handle()` einfach so auf `bot` zugreift, dürfte eigentlich nicht sein. Funktionen sollten unabhängig funktionieren und keine Abhängigkeiten zu globalen Variablen haben. So schafft man sich sonst ganz schnell unübersichtliche Programme die man nicht mehr, oder nur schwer versteht.

In diese Versuchung kommt man gar nicht erst wenn man auf Modulebene nur Code stehen hat, der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Abkürzungen bei Namen sollte man vermeiden. `message` ist klarer als `msg`.

Dateien die man öffnen, sollte man auch wieder schliessen. Hier ist die ``with``-Anweisung recht praktisch. `file` ist der Name des eingebauten Dateityps, den sollte man nicht an andere Werte binden.

Wenn man Wahrheitswerte meint, sollte man `True` und `False` verwenden und nicht 1 und 0.

Wenn das Programm auf einem Unix/Linux läuft, würde ich die Schleife am Ende durch `signal.pause()` ersetzen.


Wenn die anderen Wochentage genauso aufgebaut sind, dann braucht man kein ``if`` pro Tag im Quelltext, denn das würde ja auf Programmieren durch kopieren und einfügen hinaus laufen, sondern eine Schleife über die Namen der Wochentage. Den Code für den einzelnen Tag kann man aufgrund dieser Zeichenkette formulieren. Auch sollte man Konstante Werte wie den Pfad zu den Texten nur einmal im Programm stehen haben. Sonst macht das nur unnötig Arbeit wenn man das mal anpassen möchte, und ist fehleranfällig, weil man aufpassen muss jede Kopie des Wertes exakt gleich zu ändern.

Ich lande dann als Zwischenergebnis bei so etwas (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
import os
import signal
from functools import partial
import telepot

SECRET_TOKEN = 'Geheimer Token.'
BASE_PATH = '/home/pi/bots/Schulbot'
WEEK_DAYS = [
    'montag', 'dienstag', 'mittwoch', 'donnerstag',
    'freitag', 'samstag', 'sonntag',
]


def handle(bot, message):
    chat_id = message['chat']['id']
    command = message['text'].lower()
 
    for weekday in WEEK_DAYS:
        if weekday in command or command == weekday[:2]:
            path = os.path.join(BASE_PATH, weekday.capitalize() + '.txt')
            with open(path, 'r') as day_file:
                bot.sendMessage(chat_id, text=day_file.read())
            break


def main(): 
    bot = telepot.Bot(SECRET_TOKEN)
    bot.message_loop(partial(handle, bot))
    print('Schulbot gestartet.')
    signal.pause()


if __name__ == '__main__':
    main()
Hier kommt man noch ohne Klasse aus, aber wenn Du ein ”cooldown” einbauen möchtest, dann musst Du Dir selbst Zustand über `handle()`-Aufrufe hinweg merken der nicht in der `Bot`-Klasse gekapselt ist, also brauchst Du eine eigene Klasse.

Ich würde mir auch überlegen ob die Wochentagsdateinamen unbedingt mit einem Grossbuchstaben anfangen müssen. Dann könnte man sich nämlich das `capitalize()` sparen.
Antworten