From 56637e57ef58c84d679e878871150920b446cbd9 Mon Sep 17 00:00:00 2001 From: v0id1st Date: Fri, 10 Apr 2026 10:29:12 +0200 Subject: [PATCH] first --- .gitignore | 3 + README.md | 6 ++ irc.py | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 253 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 irc.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..525ce52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +.venv/ +stats/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..5e3dbe2 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# Boty + +W tym repozytorium znajdują się boty, które działają w ramach tylda.org +Aktualnie działające boty: + +- **irc.py** - bot do IRC, odpowiada na proste komendy typu !hello, !calc, !gn, !8ball i przy okazji zbiera liczbę wiadomości do /opt/bots/stats/stats.json, readable dla każdego. diff --git a/irc.py b/irc.py new file mode 100644 index 0000000..90f2a77 --- /dev/null +++ b/irc.py @@ -0,0 +1,244 @@ +""" +IRC bot dla tylda.org +Autor: v0id1st +Wersja: 0.1 + +Bot do zbierania statystyk na IRC tylda.org oraz dający parę gadżetów +""" + +import random +import socket +from simpleeval import simple_eval, EvalWithCompoundTypes +import math +import time +import json +from datetime import date +from pathlib import Path + +STATS_FILE = Path("stats/stats.json") + +try: + content = STATS_FILE.read_text().strip() +except FileNotFoundError: + content = "" + +FUNCTIONS = { + "sqrt": math.sqrt, + "sin": math.sin, + "cos": math.cos, + "tan": math.tan, + "asin": math.asin, + "acos": math.acos, + "atan": math.atan, + "log": math.log, + "log10": math.log10, + "log2": math.log2, + "exp": math.exp, + "abs": abs, + "round": round, + "floor": math.floor, + "ceil": math.ceil, +} + +NAMES = { + "pi": math.pi, + "e": math.e, + "tau": math.tau, + "inf": math.inf, +} + +def calc(expr): + return simple_eval(expr, functions=FUNCTIONS, names=NAMES) + +def connect_irc(): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect(("127.0.0.1", 6667)) + return s + +def send_raw(sock, message): + sock.send(f"{message}\r\n".encode("utf-8")) + print(f">> {message}") + +def send_msg(sock, sender, target, message, to_call = True): + if to_call: + call = f"{sender}: " if target.startswith("#") else "" + else: + call = "" + reply_to = target if target.startswith("#") else sender + + send_raw(sock, f"PRIVMSG {reply_to} :{call}{message}") + +def main(): + print("[+] Lacze z serwerem...") + irc = connect_irc() + print("[+] Polaczono!") + + send_raw(irc, "NICK tylda_bot") + send_raw(irc, "USER tylda_bot 0 * :Bot tyldowy") + + buffer = "" + lastmsg = "" + + while True: + data = irc.recv(4096).decode("utf-8", errors="replace") + if not data: + print("[!] Rozlaczono.") + + buffer += data + lines = buffer.split("\r\n") + buffer = lines.pop() + + for line in lines: + if not line: + continue + + print(f"<< {line}") + + if line.startswith("PING"): + pong_response = line.replace("PING", "PONG", 1) + send_raw(irc, pong_response) + continue + + if " 001 " in line: + send_raw(irc, "JOIN #test_bot") + continue + + + if "PRIVMSG" in line: + try: + content = STATS_FILE.read_text().strip() + except FileNotFoundError: + content = "" + + today = date.today().isoformat() + + if content: + stats = json.loads(content) + if stats["last_date"] != today: + stats["today_msg"] = 1 + else: + stats["today_msg"] += 1 + stats["all_msg"] += 1 + stats["last_date"] = today + else: + stats = {"last_date": today, "today_msg": 1, "all_msg": 1} + + STATS_FILE.write_text(json.dumps(stats)) + + parts = line.split(" ", 3) + if len(parts) >= 4: + sender = parts[0].split("!")[0][1:] + target = parts[2] + message = parts[3][1:].strip() + if not message.startswith("!"): + lastmsg = message + + if message == "!hello": + greetings = ["Cześć", "Siema", "Siemka", "Siemano", "Elo", "ELO", "NO ELO", "Yo", "Yooooo", "Witaj", "Siema z rana"] + greeting = random.choice(greetings) + send_msg(irc, sender, target, f"{greeting} {sender}!") + + if message == "!gn": + gns = ["Dobranoc", "Dobranocki", "Kolorowych snów", "Papa", "Paaa", "Śpij dobrze", "Śpij słodko", "Trzymaj się", "Narka"] + gn = random.choice(gns) + send_msg(irc, sender, target, f"{gn} {sender}!") + + if message == "!8ball": + answers = [ + "To pewne.", + "Zdecydowanie tak.", + "Bez wątpienia.", + "Tak - na pewno.", + "Możesz na to liczyć.", + "Jak to widzę, tak.", + "Najprawdopodobniej.", + "Perspektywy dobre.", + "Tak.", + "Znaki wskazują na tak.", + "Odpowiedź niewyraźna, spróbuj ponownie.", + "Zapytaj później.", + "Lepiej ci teraz nie mówić.", + "Nie można przewidzieć.", + "Skoncentruj się i zapytaj ponownie.", + "Nie licz na to.", + "Moja odpowiedź brzmi: nie.", + "Moje źródła mówią nie.", + "Perspektywy niezbyt dobre.", + "Bardzo wątpliwe.", + "Nie." + ] + answer = random.choice(answers) + send_msg(irc, sender, target, answer) + + if message == "!roll": + answers = [1,2,3,4,5,6] + answer = random.choice(answers) + send_msg(irc, sender, target, f"Wylosowałem: {answer}") + + if message.startswith("!rate "): + what = " ".join(message.split(" ")[1:]) + score = math.floor(random.random() * 11) + send_msg(irc, sender, target, f"Moja ocena {what} to: {score}") + + if message.startswith("!calc "): + what = " ".join(message.split(" ")[1:]) + try: + result = calc(what) + except: + result = "nope" + + msg = f"Wynik to: {result}" if result != "nope" else "Nieprawidłowy format!" + send_msg(irc, sender, target, msg) + + if message.startswith("!mock"): + what = " ".join(message.split(" ")[1:]) + if len(what) > 0: + to_mock = what + else: + to_mock = lastmsg + + mocked = "".join(c.upper() if i % 2 == 0 else c.lower() for i,c in enumerate(to_mock)) + send_msg(irc, sender, target, mocked, False) + + if message.startswith("!rps "): + what = " ".join(message.split(" ")[1:]) + if what.startswith("papier"): + choice = "paper" + elif what.startswith("kamie"): + choice = "rock" + elif what.startswith("no"): + choice = "scissors" + + mine = random.choice(["rock", "paper", "scissors"]) + if mine == "rock" and choice == "rock": + answer = "Kamień! Remis!" + elif mine == "rock" and choice == "paper": + answer = "Kamień! Gratulacje <3" + elif mine == "rock" and choice == "scissors": + answer = "Kamień! Przykro mi :(" + elif mine == "paper" and choice == "rock": + answer = "Papier! Przykro mi :((" + elif mine == "paper" and choice == "paper": + answer = "Papier! Remis! :D" + elif mine == "paper" and choice == "scissors": + answer = "Papier! Gratki <3" + elif mine == "scissors" and choice == "rock": + answer = "Nożyce! Nieźle, gratki :)" + elif mine == "scissors" and choice == "paper": + answer = "Nożyce! Sorki :c" + elif mine == "scissors" and choice == "scissors": + answer = "Nożyce! Remis xD" + + send_msg(irc, sender, target, f"Wylosowałem.. {answer}") + + if message == "!help": + send_msg(irc, sender, target, "Jestem botem, witam. Potrafię następujące rzeczy:") + time.sleep(0.5) + send_msg(irc, sender, target, "!hello, !8ball, !roll, !mock [arg], !rps , !rate oraz !calc ") + time.sleep(0.5) + send_msg(irc, sender, target, "Jak chcesz coś mi dorzucić to zapraszam na gita :))))") + + +if __name__ == "__main__": + main() +