From e2fcae32d83023a829b6ab2ae3bfae759b07e359 Mon Sep 17 00:00:00 2001 From: acidvegas Date: Thu, 21 May 2020 21:01:05 -0400 Subject: [PATCH] for fourone --- irc/bots/ircs | 1 - irc/bots/ircs/README.md | 42 +++ irc/bots/ircs/ircs/core/config.py | 20 ++ irc/bots/ircs/ircs/core/debug.py | 70 +++++ irc/bots/ircs/ircs/core/functions.py | 113 +++++++ irc/bots/ircs/ircs/core/irc.py | 433 +++++++++++++++++++++++++++ irc/bots/ircs/ircs/data/.gitignore | 1 + irc/bots/ircs/ircs/ircs.py | 20 ++ 8 files changed, 699 insertions(+), 1 deletion(-) delete mode 160000 irc/bots/ircs create mode 100644 irc/bots/ircs/README.md create mode 100644 irc/bots/ircs/ircs/core/config.py create mode 100644 irc/bots/ircs/ircs/core/debug.py create mode 100644 irc/bots/ircs/ircs/core/functions.py create mode 100644 irc/bots/ircs/ircs/core/irc.py create mode 100644 irc/bots/ircs/ircs/data/.gitignore create mode 100644 irc/bots/ircs/ircs/ircs.py diff --git a/irc/bots/ircs b/irc/bots/ircs deleted file mode 160000 index a2d36f8..0000000 --- a/irc/bots/ircs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a2d36f86df617efad0dcace56862f0a8c147d3da diff --git a/irc/bots/ircs/README.md b/irc/bots/ircs/README.md new file mode 100644 index 0000000..a1505b2 --- /dev/null +++ b/irc/bots/ircs/README.md @@ -0,0 +1,42 @@ +###### Information +This project is no longer being maintained & is made available for historical purposes only. + +The IRCS project is basically a stripped down version of [Anope](https://www.anope.org/)'s bots all crammed into one & was developed for usage with [UnrealIRCd](https://www.unrealircd.org/) 4. + +###### Setup +You will get the lowest ping having the bot connect to localhost on the same box as the IRCd is running. + +The bot *will* require network operator privledges in order to work, so make sure you add that into your IRCd configuration. + +Edit [`config.py`](https://github.com/acidvegas/ircs/blob/master/ircs/core/config.py) and change the `oper_passwd` and the `admin_host` settings. + +###### Commands +| Mode Command | Description | Restriction | +| --- | --- | --- | +| !mode \ | Read all the auto-mode hosts for \. | *+q only* | +| !mode \ \ | Read all the \ auto-mode hosts for \. | *+q only* | +| !mode \ \ +\ | Automatically +\ a user matching \. | *+q only* | +| !mode \ \ -\ | Remove automatic +\ from a user matching \. | *+q only* | +| !sync \ | Set all the channels stored in the database for \. | *+q only* | + +| Vhost Command | Description | Restriction | +| --- | --- | --- | +| !vhost add \ \ | Change the host of \ to \ on connect. | *admin only*| +| !vhost drop \ | Delete the VHOST registered to \. | *admin only* | +| !vhost list | Return a list of all activated VHOSTs. | *admin only* | +| !vhost on | Turn on your VHOST. | *vhost users only* | +| !vhost off | Turn off your VHOST. | *vhost users only*| +| !vhost sync | Change your current hostmask to your VHOST. | *vhost users only* | + +| Admin Command | Description | Restriction | +| --- | --- | --- | +| !husers | List all users connected but not joined to any channel(s). | *admin only* | +| !husers join \ | Force join all hidden users into \. | *admin only* | +| !husers kill | Kill the connection of all hidden users. | *admin only* | +| !husers gline | G:Line the connection of all hidden users. | *admin only* | +| !husers gzline | GZ:Line the connection of all hidden users. | *admin only* | + +###### Mirrors +- [acid.vegas](https://acid.vegas/random) *(main)* +- [GitHub](https://github.com/acidvegas/random) +- [GitLab](https://gitlab.com/acidvegas/random) diff --git a/irc/bots/ircs/ircs/core/config.py b/irc/bots/ircs/ircs/core/config.py new file mode 100644 index 0000000..f1af76f --- /dev/null +++ b/irc/bots/ircs/ircs/core/config.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# IRC Services (IRCS) - Developed by acidvegas in Python (https://acid.vegas/ircs) +# config.py + +# Connection +server = 'localhost' +port = 6667 +use_ipv6 = False +use_ssl = False +vhost = None +password = None + +# Identity +nickname = 'IRCS' +username = 'ircs' +realname = 'IRC Services Bot' + +# Admin +admin_host = 'CHANGEME' +oper_passwd = 'CHANGEME' diff --git a/irc/bots/ircs/ircs/core/debug.py b/irc/bots/ircs/ircs/core/debug.py new file mode 100644 index 0000000..07ce3f0 --- /dev/null +++ b/irc/bots/ircs/ircs/core/debug.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# IRC Services (IRCS) - Developed by acidvegas in Python (https://acid.vegas/ircs) +# debug.py + +import ctypes +import os +import sys +import time +import string + +def check_data(data): + if all(c in string.printable for c in data): + return True + else: + return False + +def check_privileges(): + if check_windows(): + if ctypes.windll.shell32.IsUserAnAdmin() != 0: + return True + else: + return False + else: + if os.getuid() == 0 or os.geteuid() == 0: + return True + else: + return False + +def check_version(major): + if sys.version_info.major == major: + return True + else: + return False + +def check_windows(): + if os.name == 'nt': + return True + else: + return False + +def clear(): + if check_windows(): + os.system('cls') + else: + os.system('clear') + +def error(msg, reason=None): + if reason: + print('{0} | [!] - {1} ({2})'.format(get_time(), msg, str(reason))) + else: + print('{0} | [!] - {1}'.format(get_time(), msg)) + +def error_exit(msg): + raise SystemExit('{0} | [!] - {1}'.format(get_time(), msg)) + +def get_time(): + return time.strftime('%I:%M:%S') + +def info(): + clear() + print(''.rjust(56, '#')) + print('#{0}#'.format(''.center(54))) + print('#{0}#'.format('IRC Services (IRCS)'.center(54))) + print('#{0}#'.format('Developed by acidvegas in Python'.center(54))) + print('#{0}#'.format('https://acid.vegas/ircs'.center(54))) + print('#{0}#'.format(''.center(54))) + print(''.rjust(56, '#')) + +def irc(msg): + print('{0} | [~] - {1}'.format(get_time(), msg)) \ No newline at end of file diff --git a/irc/bots/ircs/ircs/core/functions.py b/irc/bots/ircs/ircs/core/functions.py new file mode 100644 index 0000000..0af9b41 --- /dev/null +++ b/irc/bots/ircs/ircs/core/functions.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +# IRC Services (IRCS) - Developed by acidvegas in Python (https://acid.vegas/ircs) +# functions.py + +import inspect +import os +import sqlite3 +import string + +# Database +database_dir = os.path.join(os.path.dirname(os.path.realpath(inspect.stack()[-1][1])), 'data') +database_file = os.path.join(database_dir, 'ircs.db') + +# Globals +db = sqlite3.connect(database_file) +sql = db.cursor() + +class Database: + def check(): + tables = sql.execute('SELECT name FROM sqlite_master WHERE type=\'table\'').fetchall() + if len(tables): + return True + else: + return False + + def create(): + sql.execute('CREATE TABLE CHANSERV (CHANNEL TEXT NOT NULL, IDENT TEXT NOT NULL, MODE TEXT NOT NULL);') + sql.execute('CREATE TABLE HOSTSERV (IDENT TEXT NOT NULL, VHOST TEXT NOT NULL, STATUS TEXT NOT NULL);') + db.commit() + + + +class ChanServ: + def add_mode(chan, ident, mode): + sql.execute('INSERT INTO CHANSERV (CHANNEL,IDENT,MODE) VALUES (?, ?, ?)', (chan, ident, mode)) + db.commit() + + def channels(): + return set(list(item[0] for item in sql.execute('SELECT CHANNEL FROM CHANSERV ORDER BY CHANNEL ASC').fetchall())) + + def del_mode(chan, ident): + sql.execute('DELETE FROM CHANSERV WHERE CHANNEL=? AND IDENT=?', (chan, ident)) + db.commit() + + def drop(chan): + sql.execute('DELETE FROM CHANSERV WHERE CHANNEL=?', (chan,)) + db.commit() + + def get_mode(chan, ident): + data = sql.execute('SELECT MODE FROM CHANSERV WHERE CHANNEL=? AND IDENT=?', (chan, ident)).fetchone() + if data: + return data[0] + else: + return None + + def hosts(): + return set(list(item[0].split('@')[1] for item in sql.execute('SELECT IDENT FROM CHANSERV', (channel,)).fetchall())) + + def idents(chan, mode=None): + if mode: + return list(item[0] for item in sql.execute('SELECT IDENT FROM CHANSERV WHERE CHANNEL=? AND MODE=?', (channel, mode)).fetchall()) + else: + return list(item[0] for item in sql.execute('SELECT IDENT FROM CHANSERV WHERE CHANNEL=?', (channel,)).fetchall()) + + def read(channel, mode=None): + if mode: + return sql.execute('SELECT IDENT FROM CHANSERV WHERE CHANNEL=? AND MODE=? ORDER BY CHANNEL ASC, MODE ASC, IDENT ASC', (channel, mode)).fetchall() + else: + return sql.execute('SELECT IDENT,MODE FROM CHANSERV WHERE CHANNEL=? ORDER BY CHANNEL ASC, MODE ASC, IDENT ASC', (channel,)).fetchall() + + + +class HostServ: + def add(ident, vhost): + sql.execute('INSERT INTO HOSTSERV (IDENT,VHOST,STATUS) VALUES (?, ?, \'pending\')', (ident, vhost)) + db.commit() + + def delete(ident): + sql.execute('DELETE FROM HOSTSERV WHERE IDENT=?', (ident,)) + db.commit() + + def get_vhost(ident, active=False): + data = sql.execute('SELECT VHOST FROM HOSTSERV WHERE IDENT=? AND STATUS=\'on\'', (ident,)).fetchone() + if data: + return data[0] + else: + return None + + def get_status(ident): + data = sql.execute('SELECT STATUS FROM HOSTSERV WHERE IDENT=?', (ident,)).fetchone() + if data: + return data[0] + else: + return None + + def hosts(): + return set(list(item[0].split('@')[1] for item in sql.execute('SELECT IDENT FROM CHANSERV', (channel,)).fetchall())) + + def idents(): + return list(item[0] for item in sql.execute('SELECT IDENT FROM HOSTSERV').fetchall()) + + def pending(): + return sql.execute('SELECT IDENT,VHOST FROM HOSTSERV WHERE STATUS=\'pending\' ORDER BY IDENT ASC').fetchall() + + def read(): + return sql.execute('SELECT IDENT,VHOST FROM HOSTSERV ORDER BY IDENT ASC').fetchall() + + def set_status(ident, status): + sql.execute('UPDATE HOSTSERV SET STATUS=? WHERE IDENT=?', (status, ident)) + db.commit() + + def vhosts(): + return list(item[0] for item in sql.execute('SELECT VHOST FROM HOSTSERV').fetchall()) \ No newline at end of file diff --git a/irc/bots/ircs/ircs/core/irc.py b/irc/bots/ircs/ircs/core/irc.py new file mode 100644 index 0000000..e0834e5 --- /dev/null +++ b/irc/bots/ircs/ircs/core/irc.py @@ -0,0 +1,433 @@ +#!/usr/bin/env python +# IRC Services (IRCS) - Developed by acidvegas in Python (https://acid.vegas/ircs) +# irc.py + +import socket +import ssl +import time + +import config +import debug +from functions import Database, ChanServ, HostServ + +# Formatting Control Characters / Color Codes +bold = '\x02' +italic = '\x1D' +underline = '\x1F' +reverse = '\x16' +reset = '\x0f' +white = '00' +black = '01' +blue = '02' +green = '03' +red = '04' +brown = '05' +purple = '06' +orange = '07' +yellow = '08' +light_green = '09' +cyan = '10' +light_cyan = '11' +light_blue = '12' +pink = '13' +grey = '14' +light_grey = '15' + +class IRC(object): + server = config.server + port = config.port + use_ipv6 = config.use_ipv6 + use_ssl = config.use_ssl + vhost = config.vhost + password = config.password + nickname = config.nickname + username = config.username + realname = config.realname + oper_passwd = config.oper_passwd + admin_host = config.admin_host + + def __init__(self): + self.husers = list() + self.last = dict() + self.sock = None + + def action(self, chan, msg): + self.sendmsg(chan, '\x01ACTION {0}\x01'.format(msg)) + + def chghost(self, nick, host): + self.raw('CHGHOST {0} {1}'.format(nick, host)) + + def color(self, msg, foreground, background=None): + if background: + return '\x03{0},{1}{2}{3}'.format(foreground, background, msg, reset) + else: + return '\x03{0}{1}{2}'.format(foreground, msg, reset) + + def connect(self): + try: + self.create_socket() + self.sock.connect((self.server, self.port)) + if self.password: + self.raw('PASS ' + self.password) + self.raw('USER {0} 0 * :{1}'.format(self.username, self.realname)) + self.raw('NICK ' + self.nickname) + except socket.error as ex: + debug.error('Failed to connect to IRC server.', ex) + self.event_disconnect() + else: + self.listen() + + def create_socket(self): + if self.use_ipv6: + self.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + else: + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if self.vhost: + self.sock.bind((self.vhost, 0)) + if self.use_ssl: + self.sock = ssl.wrap_socket(self.sock) + + def error(self, target, msg, reason=None): + if reason: + self.sendmsg(target, '[{0}] {1} {2}'.format(self.color('ERROR', red), msg, self.color('({0})'.format(str(reason)), grey))) + else: + self.sendmsg(target, '[{0}] {1}'.format(self.color('ERROR', red), msg)) + + def event_connect(self): + self.mode(self.nickname, '+Bd') + self.oper(self.username, self.oper_passwd) + if Database.check(): + for channel in ChanServ.channels(): + self.join(channel) + else: + Database.create() + + def event_connection(self, nick, ident): + vhost = HostServ.get_vhost(ident, True) + if vhost: + self.chghost(nick, vhost) + + def event_disconnect(self): + self.sock.close() + time.sleep(10) + self.connect() + + def event_end_of_who(self): + if self.last['cmd'] == 'husers': + if self.husers: + self.sendmsg(self.last['nick'], '{0} {1}'.format(self.color('Total:', light_blue), self.color(len(self.husers), grey))) + else: + self.error(self.last['nick'], 'No hidden users found.') + + def event_join(self, nick, ident, chan): + mode = ChanServ.get_mode(chan, ident) + if mode: + self.mode(chan, '+{0} {1}'.format(mode, nick)) + + def event_kick(self, chan, kicked): + if kicked == self.nickname: + if chan in Database.channels(): + self.join(chan) + + def event_nick_in_use(self): + debug.error_exit('IRCS is already running.') + + def event_notice(self, nick, data): + if '.' in nick or nick == self.server: + args = data.split() + if 'Client connecting' in data: + nick = args[6] + ident = args[7][1:][:-1] + self.event_connection(nick, ident) + + def event_private(self, nick, ident, msg): + try: + args = msg.split() + cmd = args[0][1:] + host = ident.split('@')[1] + if cmd == 'husers' and host == self.admin_host: + if len(args) == 1: + self.husers = list() + self.last = {'nick':nick,'cmd':'husers'} + self.who('I', '*') + elif len(args) == 2: + if args[1] == 'kill': + if self.husers: + self.action(nick, 'Killing all hidden users...') + for item in self.husers: + self.kill(item['nick'], 'Killed by IRCS anti-bot protection.') + else: + self.error(nick, 'Hidden users list is empty.', 'Make sure you run !husers first') + elif args[1] == 'gzline': + if self.husers: + self.action(nick, 'Z:Lining all hidden users...') + for item in self.husers: + self.gzline(item['host'], '1d', 'Banned by IRCS anti-bot protection.') + else: + self.error(nick, 'Hidden users list is empty.', 'Make sure you run !husers first') + elif len(args) == 3: + if args [1] == 'join': + channel = args[2] + if channel.startswith('#') and len(channel) <= 20: + if self.husers: + self.action(nick, 'Joining all hidden users to {0}...'.format(channel)) + for item in self.husers: + self.sajoin(item['nick'], channel) + else: + self.error(nick, 'Hidden users list is empty.', 'Make sure you run !husers first') + else: + self.error(nick, 'Invalid arguments.') + else: + self.error(nick, 'Invalid arguments.') + else: + self.error(nick, 'Invalid arguments.') + elif cmd == 'mode': + if len(args) > 1: + channel = args[1] + if channel[:1] == '#' and len(channel) <= 20 and debug.check_data(channel): + if ChanServ.get_mode(channel, ident) == 'q' or host == self.admin_host: + if len(args) == 2: + if channel in ChanServ.channels(): + data = ChanServ.read(channel) + self.sendmsg(nick, '[{0}]'.format(self.color(channel, purple))) + for row in data: + self.sendmsg(nick, '{0} | {1}'.format(self.color('+' + row[1], grey), self.color(row[0], yellow))) + self.sendmsg(nick, '{0} {1}'.format(self.color('Total:', light_blue), self.color(len(data), grey))) + else: + self.error(nick, self.color(channel, purple) + ' does not exist.') + elif len(args) == 3: + if args[2] in ('a','h','o','v','q'): + if channel in ChanServ.channels(): + mode = args[2] + data = ChanServ.read(channel, mode) + if data: + self.sendmsg(nick, '[{0}] {1}'.format(self.color(channel, purple) , self.color('(+{0})'.format(mode), grey))) + for row in data: + self.sendmsg(nick, self.color(row[0], yellow)) + self.sendmsg(nick, '{0} {1}'.format(self.color('Total:', light_blue), self.color(len(data), grey))) + else: + self.error(nick, self.color('+{0}'.format(mode), grey) + ' is empty.') + else: + self.error(nick, self.color(channel, purple) + ' does not exist.') + else: + self.error(nick, 'Invalid arguments.') + elif len(args) == 4: + if args[2] in ('a','h','o','v','q') and args[3][:1] in '+-' and len(args[3]) <= 63 and debug.check_data(args[3]): + mode = args[2] + if mode == 'q' and host != self.admin_host: + self.error(nick, 'You do not have permission to change this mode.') + else: + action = args[3][:1] + ident = args[3][1:] + if action == '+': + if not ChanServ.get_mode(channel, ident): + ChanServ.add_mode(channel, ident, mode) + self.sendmsg(nick, '{0} {1} has been {2} to the {3} database.'.format(self.color(ident, light_blue), self.color('(+{0})'.format(mode), grey), self.color('added', green), self.color(channel, purple))) + else: + self.error(nick, '{0} already exists in the {1} database.'.format(self.color(ident, light_blue), self.color(channel, purple))) + elif action == '-': + if ChanServ.get_mode(channel, ident): + ChanServ.del_mode(channel, ident) + self.sendmsg(nick, '{0} {1} has been {2} from the {3} database.'.format(self.color(ident, light_blue), self.color('(+{0})'.format(mode), grey), self.color('removed', red), self.color(channel, purple))) + else: + self.error(nick, '{0} does not exist in the {1} database.'.format(self.color(ident, light_blue), self.color(channel, purple))) + else: + self.error(nick, 'Invalid arguments.') + else: + self.error(nick, 'Invalid arguments.') + else: + self.error(nick, 'You do not have permission to use this command.') + else: + self.error(nick, 'Invalid arguments.') + else: + self.error(nick, 'Invalid arguments.') + elif cmd == 'sync': + if len(args) == 2: + channel = args[1] + if channel[:1] == '#' and len(channel) <= 20 and debug.check_data(channel): + if channel in ChanServ.channels(): + if ChanServ.get_mode(channel, ident) == 'q' or host == self.admin_host: + self.action(nick, 'Syncing all modes in {0}...'.format(color(channel, purple))) + self.last['cmd'] = 'sync ' + channel + self.who('h', '*') + else: + self.error(nick, 'You do not have permission to use this command.') + else: + self.error(nick, '{0} does not exist.'.format(color(channel, purple))) + else: + self.error(nick, 'Invalid arguments.') + else: + self.error(nick, 'Invalid arguments.') + elif cmd == 'vhost': + if len(args) == 2: + if args[1] == 'list': + if host == self.admin_host: + vhosts = HostServ.read() + if vhosts: + self.sendmsg(nick, '[{0}]'.format(self.color('Registered Vhosts', purple))) + for vhost in vhosts: + self.sendmsg(nick, '{0} {1}'.format(self.color(vhost[0], yellow), self.color('({0})'.format(vhost[1]), grey))) + self.sendmsg(nick, '{0} {1}'.format(self.color('Total:', light_blue), self.color(len(vhosts), grey))) + else: + self.error(nick, 'Vhost list is empty.') + else: + self.error(nick, 'You do not have permission to use this command.') + elif args[1] == 'off': + status = HostServ.get_status(ident) + if status == 'off': + self.error(nick, 'VHOST is already turned off.') + elif status == 'on': + HostServ.set_status(ident, 'off') + self.sendmsg(nick, 'VHOST has been turned ' + color('off', red)) + else: + self.error(nick, 'You do not have a registered VHOST.') + elif args[1] == 'on': + status = HostServ.get_status(ident) + if status == 'off': + HostServ.set_status(ident, 'on') + self.sendmsg(nick, 'VHOST has been turned ' + color('on', green)) + elif status == 'on': + self.error(nick, 'Your VHOST is already turned on.') + else: + self.error(nick, 'You do not have a registered VHOST.') + elif args[1] == 'sync': + vhost = HostServ.get_vhost(ident) + if host == vhost: + self.error(nick, 'Your VHOST is already synced and working.') + elif vhost: + self.action(nick, 'Syncing VHOST...') + self.chghost(nick, vhost) + else: + self.error(nick, 'You do not have a registered VHOST.') + elif len(args) == 3: + if args[1] == 'drop': + if host == self.admin_host: + ident = args[2] + if ident in HostServ.idents(): + HostServ.delete(ident) + self.sendmsg(nick, '{0} has been {1} from the vhost database.'.format(self.color(ident, light_blue), self.color('removed', red))) + else: + self.error(nick, '{0} does not have a vhost.'.format(self.color(ident, light_blue))) + else: + self.error(nick, 'You do not have permission to use this command.') + elif len(args) == 4: + if args[1] == 'add': + if host == self.admin_host: + ident = args[2] + vhost = args[3] + if ident not in HostServ.idents(): + HostServ.add(ident, vhost) + self.sendmsg(nick, '{0} has been {1} from the database.'.format(self.color(ident, light_blue), self.color('added', green))) + else: + self.error(nick, '{0} is already registered.'.format(color(ident, light_blue))) + else: + self.error(nick, 'You do not have permission to use this command.') + else: + self.error(nick, 'Invalid arguments.') + else: + self.error(nick, 'Invalid arguments.') + except Exception as ex: + self.error(nick, 'Unexpected error has occured.', ex) + + def event_who(self, chan, user, host, nick): + if self.last: + if self.last['cmd'] == 'husers': + if chan == '*': + self.husers.append({'user':user,'host':host,'nick':nick}) + self.sendmsg(self.last['nick'], '{0} {1}'.format(self.color(nick, yellow), self.color('({0}@{1})'.format(user, host), grey))) + elif self.last['cmd'].startswith('sync'): + channel = self.last['cmd'].split()[1] + if chan == channel: + mode = ChanServ.mode(chan, '{0}@{1]'.format(user, host)) + if mode: + self.mode(chan, '+{0} {1}'.format(mode, nick)) + + def gzline(self, host, duration, msg): + self.raw('gzline *@{1} {2} {3}'.format(user, host, duration, msg)) + + def handle_events(self, data): + args = data.split() + if args[0] == 'PING': + self.raw('PONG ' + args[1][1:]) + elif args[1] == '001': + self.event_connect() + elif args[1] == '315': + self.event_end_of_who() + elif args[1] == '352': + chan = args[3] + user = args[4] + host = args[5] + nick = args[7] + self.event_who(chan, user, host, nick) + elif args[1] == '433': + self.event_nick_in_use() + elif args[1] == 'NOTICE': + nick = args[0][1:] + self.event_notice(nick, data) + elif args[1] in ('JOIN','KICK','PRIVMSG'): + nick = args[0].split('!')[0][1:] + if nick != self.nickname: + chan = args[2] + if args[1] == 'JOIN': + host = args[0].split('!')[1] + self.event_join(nick, host, chan[1:]) + elif args[1] == 'KICK': + kicked = args[3] + self.event_kick(chan, kicked) + elif args[1] == 'PRIVMSG': + ident = args[0].split('!')[1] + msg = data.split('{0} PRIVMSG {1} :'.format(args[0], chan))[1] + if msg.startswith('!'): + if chan == self.nickname: + self.event_private(nick, ident, msg) + + def join(self, chan): + self.raw('JOIN ' + chan) + self.mode(chan, '+q ' + self.nickname) + + def kill(self, nick, reason): + self.raw('KILL {0} {1}'.format(nick, reason)) + + def listen(self): + while True: + try: + data = self.sock.recv(1024).decode('utf-8') + if data: + for line in (line for line in data.split('\r\n') if line): + debug.irc(line) + if line.startswith('ERROR :Closing Link:'): + raise Exception('Connection has closed.') + elif len(line.split()) >= 2: + self.handle_events(line) + else: + debug.error('No data recieved from server.') + break + except (UnicodeDecodeError,UnicodeEncodeError): + debug.error('Unicode error has occured.') + except Exception as ex: + debug.error('Unexpected error occured.', ex) + break + self.event_disconnect() + + def mode(self, target, mode): + self.raw('MODE {0} {1}'.format(target, mode)) + + def oper(self, nick, password): + self.raw('OPER {0} {1}'.format(nick, password)) + + def part(self, chan, msg): + self.raw('PART {0} {1}'.format(chan, msg)) + + def raw(self, msg): + self.sock.send(bytes(msg + '\r\n', 'utf-8')) + + def sajoin(self, nick, chan): + self.raw('SAJOIN {0} {1}'.format(nick, chan)) + + def sendmsg(self, target, msg): + self.raw('PRIVMSG {0} :{1}'.format(target, msg)) + + def who(self, flag, args): + self.raw('who +{0} {1}'.format(flag, args)) + +IRCS = IRC() \ No newline at end of file diff --git a/irc/bots/ircs/ircs/data/.gitignore b/irc/bots/ircs/ircs/data/.gitignore new file mode 100644 index 0000000..b722e9e --- /dev/null +++ b/irc/bots/ircs/ircs/data/.gitignore @@ -0,0 +1 @@ +!.gitignore \ No newline at end of file diff --git a/irc/bots/ircs/ircs/ircs.py b/irc/bots/ircs/ircs/ircs.py new file mode 100644 index 0000000..0ec026f --- /dev/null +++ b/irc/bots/ircs/ircs/ircs.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# IRC Services (IRCS) - Developed by acidvegas in Python (https://acid.vegas/ircs) +# ircs.py + +import os +import sys + +sys.dont_write_bytecode = True +os.chdir(sys.path[0] or '.') +sys.path += ('core',) + +import debug +import irc + +debug.info() +if not debug.check_version(3): + debug.error_exit('IRCS requires Python 3!') +if debug.check_privileges(): + debug.error_exit('Do not run IRCS as admin/root!') +irc.IRCS.connect()