mirror of
https://github.com/nichkara/InfinitumBotty.git
synced 2026-06-10 22:26:23 +02:00
Initalize repo
This commit is contained in:
165
FaustBot/Communication/Connection.py
Normal file
165
FaustBot/Communication/Connection.py
Normal file
@@ -0,0 +1,165 @@
|
||||
import _thread
|
||||
import queue
|
||||
import socket
|
||||
import time
|
||||
from threading import Condition
|
||||
|
||||
from FaustBot.Communication.JoinObservable import JoinObservable
|
||||
from FaustBot.Communication.KickObservable import KickObservable
|
||||
from FaustBot.Communication.LeaveObservable import LeaveObservable
|
||||
from FaustBot.Communication.MagicNumberObservable import MagicNumberObservable
|
||||
from FaustBot.Communication.NickChangeObservable import NickChangeObservable
|
||||
from FaustBot.Communication.NoticeObservable import NoticeObservable
|
||||
from FaustBot.Communication.PingObservable import PingObservable
|
||||
from FaustBot.Communication.PrivmsgObservable import PrivmsgObservable
|
||||
from FaustBot.Model.ConnectionDetails import ConnectionDetails
|
||||
from FaustBot.StringBuffer import StringBuffer
|
||||
|
||||
|
||||
class Connection(object):
|
||||
send_queue = queue.Queue()
|
||||
details = None
|
||||
irc = None
|
||||
|
||||
def sender(self):
|
||||
while True:
|
||||
msg = self.send_queue.get()
|
||||
if msg[-1] != b'\n':
|
||||
msg = msg + b'\n'
|
||||
self.irc.send(msg)
|
||||
time.sleep(1)
|
||||
|
||||
def send_channel(self, text):
|
||||
"""
|
||||
Send to channel
|
||||
:return:
|
||||
"""
|
||||
self.raw_send("PRIVMSG " + self.details.get_channel() + " :" + text[0:])
|
||||
|
||||
def send_to_user(self, user, text):
|
||||
"""
|
||||
Send to user
|
||||
:return:
|
||||
"""
|
||||
self.raw_send('PRIVMSG ' + user + ' :' + text)
|
||||
|
||||
def send_back(self, text, data):
|
||||
"""
|
||||
Send message to the channel the command got received in
|
||||
:param message:
|
||||
:param data: needed because of concurrency, there can't be a global variable holding where messages came from
|
||||
:return:
|
||||
"""
|
||||
if data['channel'] == self.details.get_nick():
|
||||
self.send_to_user(data['nick'], text)
|
||||
else:
|
||||
self.send_channel(text)
|
||||
|
||||
def raw_send(self, message):
|
||||
self.send_queue.put(message.encode() + '\r\n'.encode())
|
||||
|
||||
def receive(self):
|
||||
"""
|
||||
receive from Network
|
||||
"""
|
||||
try:
|
||||
data = self.irc.recv(4096)
|
||||
if len(data) == 0:
|
||||
return False
|
||||
except socket.timeout:
|
||||
return False
|
||||
data = data.decode('UTF-8', errors='replace')
|
||||
#print('received: \n' + data)
|
||||
data_lines = self._receiver_buffer.append(data)
|
||||
if data is None:
|
||||
return False
|
||||
# print('splited: ')
|
||||
for data in data_lines:
|
||||
# print(data)
|
||||
data = data.rstrip()
|
||||
self.data = data
|
||||
|
||||
splited = data.split(' ')
|
||||
if not len(splited) >= 2:
|
||||
continue
|
||||
command = splited[1]
|
||||
# print(command)
|
||||
if data.split(' ')[0] == 'PING':
|
||||
self.ping_observable.input(data, self)
|
||||
elif command == 'JOIN':
|
||||
self.join_observable.input(data, self)
|
||||
elif command == 'PART' or command == 'QUIT':
|
||||
self.leave_observable.input(data, self)
|
||||
elif command == 'KICK':
|
||||
self.kick_observable.input(data, self)
|
||||
elif command == 'NICK':
|
||||
self.nick_change_observable.input(data, self)
|
||||
elif command == 'NOTICE':
|
||||
self.notice_observable.input(data, self)
|
||||
elif command == 'PRIVMSG':
|
||||
self.priv_msg_observable.input(data, self)
|
||||
else:
|
||||
try:
|
||||
int(command)
|
||||
self.magic_number_observable.input(data, self)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return True
|
||||
|
||||
def is_idented(self, user: str):
|
||||
self.send_to_user('NickServ', 'ACC ' + user)
|
||||
with self.condition_lock:
|
||||
while user not in self.idented_look_up:
|
||||
self.condition_lock.wait()
|
||||
is_idented = self.idented_look_up[user]
|
||||
del self.idented_look_up[user]
|
||||
return is_idented
|
||||
|
||||
def is_op(self, user):
|
||||
"""
|
||||
Checks wether the given user is an op in this connections' channel or not.
|
||||
:param user: the user to check
|
||||
:return: return true if the user is an op, else false
|
||||
"""
|
||||
# add call to raw send with WHO
|
||||
# manualy receive data until answer received
|
||||
# then evaluate and return
|
||||
# this way we'll block the bot until is_op is finished
|
||||
return False
|
||||
|
||||
def last_data(self):
|
||||
return self.data
|
||||
|
||||
def establish(self):
|
||||
"""
|
||||
establish the connection
|
||||
"""
|
||||
self.irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
self.irc.connect((self.details.get_server(), self.details.get_port()))
|
||||
#print(self.irc.recv(512))
|
||||
self.irc.send("NICK ".encode() + self.details.get_nick().encode() + "\r\n".encode())
|
||||
self.irc.send("USER botty botty botty :Botty \n".encode())
|
||||
self.irc.send("JOIN ".encode() + self.details.get_channel().encode() + '\r\n'.encode())
|
||||
self.irc.send("WHO ".encode() + self.details.get_channel().encode() + '\r\n'.encode())
|
||||
self.irc.send("MODE ".encode()+self.details.get_nick().encode()+" -R".encode()+'\r\n'.encode())
|
||||
if (self.details.get_pwd() != ''):
|
||||
self.send_to_user("NICKSERV","identify "+self.details.get_nick()+" " +self.details.get_pwd()+' ')
|
||||
|
||||
_thread.start_new_thread(self.sender, ())
|
||||
|
||||
def __init__(self, set_details: ConnectionDetails):
|
||||
self.details = set_details
|
||||
self.ping_observable = PingObservable()
|
||||
self.priv_msg_observable = PrivmsgObservable()
|
||||
self.join_observable = JoinObservable()
|
||||
self.leave_observable = LeaveObservable()
|
||||
self.kick_observable = KickObservable()
|
||||
self.nick_change_observable = NickChangeObservable()
|
||||
self.notice_observable = NoticeObservable()
|
||||
self.magic_number_observable = MagicNumberObservable()
|
||||
self.condition_lock = Condition()
|
||||
self.idented_look_up = {}
|
||||
self.data = None
|
||||
self._receiver_buffer = StringBuffer()
|
||||
9
FaustBot/Communication/DebugPrint.py
Normal file
9
FaustBot/Communication/DebugPrint.py
Normal file
@@ -0,0 +1,9 @@
|
||||
__author__ = 'Daniela'
|
||||
|
||||
|
||||
class DebugPrint(object):
|
||||
def print(self, message):
|
||||
"""
|
||||
:param message: What to print to debug output
|
||||
:return:
|
||||
"""
|
||||
24
FaustBot/Communication/JoinObservable.py
Normal file
24
FaustBot/Communication/JoinObservable.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import _thread
|
||||
|
||||
from FaustBot.Communication.Observable import Observable
|
||||
|
||||
|
||||
class JoinObservable(Observable):
|
||||
def input(self, raw_data, connection):
|
||||
# ":nick!user@host" "JOIN" "#channel"
|
||||
# additional ignored arguments are put into "ign". This could be used
|
||||
# for http://ircv3.net/specs/extensions/extended-join-3.1.html in the
|
||||
# future.
|
||||
prefix, cmd, channel, *ign = raw_data.split(' ')
|
||||
hostmask = prefix.lstrip(':')
|
||||
nick, userhost = hostmask.split('!')
|
||||
user, host = userhost.split('@')
|
||||
|
||||
data = {'raw': raw_data, 'nick': nick, 'user': user, 'host': host,
|
||||
'channel': channel, 'raw_nick': hostmask}
|
||||
self.notify_observers(data, connection)
|
||||
|
||||
|
||||
def notify_observers(self, data, connection):
|
||||
for observer in self._observers:
|
||||
_thread.start_new_thread(observer.__class__.update_on_join, (observer, data, connection))
|
||||
20
FaustBot/Communication/KickObservable.py
Normal file
20
FaustBot/Communication/KickObservable.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import _thread
|
||||
|
||||
from FaustBot.Communication.Observable import Observable
|
||||
|
||||
|
||||
class KickObservable(Observable):
|
||||
def input(self, raw_data, connection):
|
||||
data = {}
|
||||
print(raw_data)
|
||||
data['raw'] = raw_data
|
||||
data['op'] = raw_data.split('!')[0][1:]
|
||||
data['channel'] = raw_data.split('KICK ')[1].split(' :')[0].split(' ')[0]
|
||||
data['nick'] = raw_data.split('KICK ')[1].split(' :')[0].split(' ')[1]
|
||||
data['raw_op'] = raw_data.split(' KICK')[0][1:]
|
||||
data['reason'] = raw_data.split('KICK ')[1].split(' :')[1]
|
||||
self.notify_observers(data, connection)
|
||||
|
||||
def notify_observers(self, data, connection):
|
||||
for observer in self._observers:
|
||||
_thread.start_new_thread(observer.__class__.update_on_kick, (observer, data, connection))
|
||||
18
FaustBot/Communication/LeaveObservable.py
Normal file
18
FaustBot/Communication/LeaveObservable.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import _thread
|
||||
|
||||
from FaustBot.Communication.Observable import Observable
|
||||
|
||||
|
||||
class LeaveObservable(Observable):
|
||||
def input(self, raw_data, connection):
|
||||
data = {}
|
||||
leave_or_part = "PART" if raw_data.find('PART') != -1 else "QUIT"
|
||||
data['raw'] = raw_data
|
||||
data['nick'] = raw_data.split('!')[0][1:]
|
||||
data['channel'] = raw_data.split(leave_or_part + ' ')[1].split(' :')[0]
|
||||
data['raw_nick'] = raw_data.split(' ' + leave_or_part)[0][1:]
|
||||
self.notify_observers(data, connection)
|
||||
|
||||
def notify_observers(self, data, connection):
|
||||
for observer in self._observers:
|
||||
_thread.start_new_thread(observer.__class__.update_on_leave, (observer, data, connection))
|
||||
21
FaustBot/Communication/MagicNumberObservable.py
Normal file
21
FaustBot/Communication/MagicNumberObservable.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import _thread
|
||||
|
||||
from FaustBot.Communication.Observable import Observable
|
||||
|
||||
|
||||
class MagicNumberObservable(Observable):
|
||||
def input(self, raw_data, connection):
|
||||
data = {}
|
||||
data['raw'] = raw_data
|
||||
prefix, numeric, rest = data['raw'].split(' ',2)
|
||||
data['number'] = numeric
|
||||
data['arguments'] = rest
|
||||
self.notify_observers(data, connection)
|
||||
|
||||
def notify_observers(self, data, connection):
|
||||
for observer in self._observers:
|
||||
try:
|
||||
_thread.start_new_thread(observer.__class__.update_on_magic_number, (observer, data, connection))
|
||||
except Exception:
|
||||
import traceback
|
||||
print (traceback.format_exc())
|
||||
14
FaustBot/Communication/NickChangeObservable.py
Normal file
14
FaustBot/Communication/NickChangeObservable.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import _thread
|
||||
|
||||
from FaustBot.Communication.Observable import Observable
|
||||
|
||||
|
||||
class NickChangeObservable(Observable):
|
||||
def input(self, raw_data, connection):
|
||||
data = {'raw': raw_data, 'old_nick': raw_data.split('!')[0][1:],
|
||||
'new_nick': raw_data.split('NICK ')[1].split(':')[1], 'raw_nick': raw_data.split(' NICK')[0][1:]}
|
||||
self.notify_observers(data, connection)
|
||||
|
||||
def notify_observers(self, data, connection):
|
||||
for observer in self._observers:
|
||||
_thread.start_new_thread(observer.__class__.update_on_nick_change, (observer, data, connection))
|
||||
14
FaustBot/Communication/NoticeObservable.py
Normal file
14
FaustBot/Communication/NoticeObservable.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import _thread
|
||||
|
||||
from FaustBot.Communication.Observable import Observable
|
||||
|
||||
|
||||
class NoticeObservable(Observable):
|
||||
def notify_observers(self, data, connection):
|
||||
for observer in self._observers:
|
||||
_thread.start_new_thread(observer.__class__.update_on_notice, (observer, data, connection))
|
||||
|
||||
def input(self, raw_data, connection):
|
||||
data = {'raw_data': raw_data, 'nick': raw_data.split('!')[0][1:], 'raw_nick': raw_data.split(' NOTICE ')[0][1:],
|
||||
'message': raw_data.split(':')[2]}
|
||||
self.notify_observers(data, connection)
|
||||
23
FaustBot/Communication/Observable.py
Normal file
23
FaustBot/Communication/Observable.py
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
class Observable(object):
|
||||
def __init__(self):
|
||||
self._observers = []
|
||||
|
||||
def add_observer(self, observer):
|
||||
self._observers.append(observer)
|
||||
print("appended(" + str(observer.__class__) + ")")
|
||||
|
||||
def get_observer(self):
|
||||
return self._observers
|
||||
|
||||
# data has to be a dictionary matching the structure of the query
|
||||
def notify_observers(self, data, connection):
|
||||
# here implement some data handling. Fill self._data with the data received
|
||||
raise NotImplementedError("Some Observable doesn't know what to do with its input data")
|
||||
|
||||
def input(self, raw_data, connection):
|
||||
# here implement some data handling. Fill self._data with the data received
|
||||
raise NotImplementedError("Some Observable doesn't know what to do with its input data")
|
||||
|
||||
def rm_observer(self, observer):
|
||||
self._observers.remove(observer)
|
||||
20
FaustBot/Communication/PingObservable.py
Normal file
20
FaustBot/Communication/PingObservable.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import _thread
|
||||
|
||||
from FaustBot.Communication.Observable import Observable
|
||||
|
||||
|
||||
class PingObservable(Observable):
|
||||
def input(self, raw_data, connection):
|
||||
data = {'raw': raw_data, 'server': ''}
|
||||
if raw_data.find('PING') == 0:
|
||||
data['server'] = raw_data.split('PING ')[1]
|
||||
else:
|
||||
return
|
||||
# hier kann noch gecheckt werden, ob data wirklich ein server ist, der ping haben will, oder sonstwas
|
||||
# finde heraus, wer zurückgepingt werden muss, und ob das überhaupt ein ping-request ist oder ein user sich
|
||||
# einen spass erlaubt hat
|
||||
self.notify_observers(data, connection)
|
||||
|
||||
def notify_observers(self, data, connection):
|
||||
for observer in self._observers:
|
||||
_thread.start_new_thread(observer.__class__.update_on_ping, (observer, data, connection))
|
||||
37
FaustBot/Communication/PrivmsgObservable.py
Normal file
37
FaustBot/Communication/PrivmsgObservable.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import _thread
|
||||
|
||||
from FaustBot.Communication.Observable import Observable
|
||||
from FaustBot import Modules
|
||||
from FaustBot.Model.BlockedUsers import BlockProvider
|
||||
class PrivmsgObservable(Observable):
|
||||
def __init__(self):
|
||||
Observable.__init__(self)
|
||||
self.user_list = None
|
||||
def define_user_list(self, user_list):
|
||||
self.user_list = user_list
|
||||
|
||||
def input(self, raw_data, connection):
|
||||
data = {'raw': raw_data, 'nick': raw_data.split('!')[0][1:],
|
||||
'channel': raw_data.split('PRIVMSG ')[1].split(' :')[0],
|
||||
'raw_nick': raw_data.split(' PRIVMSG')[0][1:]}
|
||||
# 12 = :<raw_nick> PRIVMSG <channel> :<message>
|
||||
data['message'] = raw_data[data['raw_nick'].__len__() + data['channel'].__len__() + 12:]
|
||||
data['command'] = 'irgendwas, das mit . oder .. anfängt oder so... oder das sollen module checken?'
|
||||
if self.user_list is None:
|
||||
return
|
||||
if data['nick'] not in self.user_list.userList.keys():
|
||||
return
|
||||
blocklist = BlockProvider()
|
||||
if blocklist.is_blocked(data['nick']):
|
||||
self.notify_whitelisted_observers(data, connection)
|
||||
return
|
||||
self.notify_observers(data, connection)
|
||||
|
||||
def notify_observers(self, data, connection):
|
||||
for observer in self._observers:
|
||||
_thread.start_new_thread(observer.__class__.update_on_priv_msg, (observer, data, connection))
|
||||
|
||||
def notify_whitelisted_observers(self,data,connection):
|
||||
for observer in self._observers:
|
||||
if observer.__class__.__name__ in ['ActivityObserver']:
|
||||
_thread.start_new_thread(observer.__class__.update_on_priv_msg, (observer, data, connection))
|
||||
1
FaustBot/Communication/__init__.py
Normal file
1
FaustBot/Communication/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
__author__ = 'Pups'
|
||||
Reference in New Issue
Block a user