commit 11ceb7fba6a96a8e6e308107858fd82eac0941d3 Author: acidvegas Date: Mon Jun 24 22:13:57 2019 -0400 Initial commit diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..69997e8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2019, acidvegas + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..06b5053 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +###### Requirments +* [Python](https://www.python.org/downloads/) *(**Note:** This script was developed to be used with the latest version of Python.)* +* [PySocks](https://pypi.python.org/pypi/PySocks) *(**Optional:** For using the `proxy` setting.)* +* [beautifulsoup4](https://pypi.python.org/pypi/beautifulsoup4) +* [google-api-python-client](https://pypi.python.org/pypi/google-api-python-client) + +###### Commands +| Command | Description | +| --- | --- | +| @dickserv | Information about the bot. | +| @dickserv help | Information about the commands. | +| coin \ | Get the USD value for \. | +| date | Get the current date and time. | +| define \ | Get the definition of \. | +| drug \ | Lookup information on \ on tripsit. | +| g \ | Search Google for \. | +| imdb \ [year] | Search \ on IMDb. | +| isup \ | Check if \ is up or not. | +| netsplit \ | Search for \ on NetSplit. | +| r \ | Read top posts from \ | +| talent | RIP DITTLE DIP DIP DIP DIP IT\'S YA BIRTHDAY!!1@11! | +| todo | Read your todo list. | +| todo add \ | Add \ to your todo list. | +| todo del \| | Delete the \ todo result. | +| tpb \ | Searc \ | Get the urban dictionary definition of \. | +| uptime | Get the amount of time DickServ has been running. | +| w \ | Get the weather for \. | +| wolfram \ | Get the results of \ from WolframAlpha. | +| yt \ | Search \ on YouTube. | + +###### Admin Commands (Private Message) +| Command | Description | +| --- | --- | +| config | View the config settings. | +| config \ \ | Change \ to \. | +| ignore | View the ignore list. | +| ignore add \ | Add a user to the ignore list. | +| ignore del \ | Remove a user from the ignore list. | +| ignore reset | Remove all ignores. | +| off | Toggle the usage of the bot commands. | +| on | Toggle the usage of the bot commands. | +| todo | List all todos. | +| todo expire | Remove all expired todos. | +| todo reset | Remove all todos. | + +###### Mirrors +- [acid.vegas](https://acid.vegas/dickserv) *(main)* +- [SuperNETs](https://git.supernets.org/acidvegas/dickserv) +- [GitHub](https://github.com/acidvegas/dickserv) +- [GitLab](https://gitlab.com/acidvegas/dickserv) diff --git a/dickserv/core/commands.py b/dickserv/core/commands.py new file mode 100644 index 0000000..6903dfe --- /dev/null +++ b/dickserv/core/commands.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# commands.py + +import cryptocurrency +import dictionary +import google +import imdb +import isup +import netsplit +import reddit +import tpb +import tripsit +import weather +import wolfram +import youtube \ No newline at end of file diff --git a/dickserv/core/config.py b/dickserv/core/config.py new file mode 100644 index 0000000..cd663c2 --- /dev/null +++ b/dickserv/core/config.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# config.py + +class connection: + server = 'irc.server.com' + port = 6697 + ipv6 = False + ssl = True + ssl_verify = False + proxy = None + vhost = None + channel = '#chats' + key = None + +class cert: + key = None + file = None + password = None + +class ident: + nickname = 'DickServ' + username = 'dickserv' + realname = 'acid.vegas/dickserv' + +class login: + network = None + nickserv = None + operator = None + +class settings: + admin = 'user@host.name' + cmd_char = '.' + log = False + modes = None + +class api: + google_api_key = 'CHANGEME' # https://console.developers.google.com/ + google_cse_id = 'CHANGEME' # https://cse.google.com/ + omdbapi_key = 'CHANGEME' # http://www.omdbapi.com/apikey.aspx + wolfram_api_key = 'CHANGEME' # http://products.wolframalpha.com/api/ + wunderground_api_key = 'CHANGEME' # https://www.wunderground.com/weather/api/ diff --git a/dickserv/core/constants.py b/dickserv/core/constants.py new file mode 100644 index 0000000..2f1a041 --- /dev/null +++ b/dickserv/core/constants.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# constants.py + +# Control Characters +bold = '\x02' +color = '\x03' +italic = '\x1D' +underline = '\x1F' +reverse = '\x16' +reset = '\x0f' + +# Color Codes +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' + +# Events +PASS = 'PASS' +NICK = 'NICK' +USER = 'USER' +OPER = 'OPER' +MODE = 'MODE' +SERVICE = 'SERVICE' +QUIT = 'QUIT' +SQUIT = 'SQUIT' +JOIN = 'JOIN' +PART = 'PART' +TOPIC = 'TOPIC' +NAMES = 'NAMES' +LIST = 'LIST' +INVITE = 'INVITE' +KICK = 'KICK' +PRIVMSG = 'PRIVMSG' +NOTICE = 'NOTICE' +MOTD = 'MOTD' +LUSERS = 'LUSERS' +VERSION = 'VERSION' +STATS = 'STATS' +LINKS = 'LINKS' +TIME = 'TIME' +CONNECT = 'CONNECT' +TRACE = 'TRACE' +ADMIN = 'ADMIN' +INFO = 'INFO' +SERVLIST = 'SERVLIST' +SQUERY = 'SQUERY' +WHO = 'WHO' +WHOIS = 'WHOIS' +WHOWAS = 'WHOWAS' +KILL = 'KILL' +PING = 'PING' +PONG = 'PONG' +ERROR = 'ERROR' +AWAY = 'AWAY' +REHASH = 'REHASH' +DIE = 'DIE' +RESTART = 'RESTART' +SUMMON = 'SUMMON' +USERS = 'USERS' +WALLOPS = 'WALLOPS' +USERHOST = 'USERHOST' +ISON = 'ISON' + +# Event Numerics +RPL_WELCOME = '001' +RPL_YOURHOST = '002' +RPL_CREATED = '003' +RPL_MYINFO = '004' +RPL_ISUPPORT = '005' +RPL_TRACELINK = '200' +RPL_TRACECONNECTING = '201' +RPL_TRACEHANDSHAKE = '202' +RPL_TRACEUNKNOWN = '203' +RPL_TRACEOPERATOR = '204' +RPL_TRACEUSER = '205' +RPL_TRACESERVER = '206' +RPL_TRACESERVICE = '207' +RPL_TRACENEWTYPE = '208' +RPL_TRACECLASS = '209' +RPL_STATSLINKINFO = '211' +RPL_STATSCOMMANDS = '212' +RPL_STATSCLINE = '213' +RPL_STATSILINE = '215' +RPL_STATSKLINE = '216' +RPL_STATSYLINE = '218' +RPL_ENDOFSTATS = '219' +RPL_UMODEIS = '221' +RPL_SERVLIST = '234' +RPL_SERVLISTEND = '235' +RPL_STATSLLINE = '241' +RPL_STATSUPTIME = '242' +RPL_STATSOLINE = '243' +RPL_STATSHLINE = '244' +RPL_LUSERCLIENT = '251' +RPL_LUSEROP = '252' +RPL_LUSERUNKNOWN = '253' +RPL_LUSERCHANNELS = '254' +RPL_LUSERME = '255' +RPL_ADMINME = '256' +RPL_ADMINLOC1 = '257' +RPL_ADMINLOC2 = '258' +RPL_ADMINEMAIL = '259' +RPL_TRACELOG = '261' +RPL_TRYAGAIN = '263' +RPL_NONE = '300' +RPL_AWAY = '301' +RPL_USERHOST = '302' +RPL_ISON = '303' +RPL_UNAWAY = '305' +RPL_NOWAWAY = '306' +RPL_WHOISUSER = '311' +RPL_WHOISSERVER = '312' +RPL_WHOISOPERATOR = '313' +RPL_WHOWASUSER = '314' +RPL_ENDOFWHO = '315' +RPL_WHOISIDLE = '317' +RPL_ENDOFWHOIS = '318' +RPL_WHOISCHANNELS = '319' +RPL_LIST = '322' +RPL_LISTEND = '323' +RPL_CHANNELMODEIS = '324' +RPL_NOTOPIC = '331' +RPL_TOPIC = '332' +RPL_INVITING = '341' +RPL_INVITELIST = '346' +RPL_ENDOFINVITELIST = '347' +RPL_EXCEPTLIST = '348' +RPL_ENDOFEXCEPTLIST = '349' +RPL_VERSION = '351' +RPL_WHOREPLY = '352' +RPL_NAMREPLY = '353' +RPL_LINKS = '364' +RPL_ENDOFLINKS = '365' +RPL_ENDOFNAMES = '366' +RPL_BANLIST = '367' +RPL_ENDOFBANLIST = '368' +RPL_ENDOFWHOWAS = '369' +RPL_INFO = '371' +RPL_MOTD = '372' +RPL_ENDOFINFO = '374' +RPL_MOTDSTART = '375' +RPL_ENDOFMOTD = '376' +RPL_YOUREOPER = '381' +RPL_REHASHING = '382' +RPL_YOURESERVICE = '383' +RPL_TIME = '391' +RPL_USERSSTART = '392' +RPL_USERS = '393' +RPL_ENDOFUSERS = '394' +RPL_NOUSERS = '395' +ERR_NOSUCHNICK = '401' +ERR_NOSUCHSERVER = '402' +ERR_NOSUCHCHANNEL = '403' +ERR_CANNOTSENDTOCHAN = '404' +ERR_TOOMANYCHANNELS = '405' +ERR_WASNOSUCHNICK = '406' +ERR_TOOMANYTARGETS = '407' +ERR_NOSUCHSERVICE = '408' +ERR_NOORIGIN = '409' +ERR_NORECIPIENT = '411' +ERR_NOTEXTTOSEND = '412' +ERR_NOTOPLEVEL = '413' +ERR_WILDTOPLEVEL = '414' +ERR_BADMASK = '415' +ERR_UNKNOWNCOMMAND = '421' +ERR_NOMOTD = '422' +ERR_NOADMININFO = '423' +ERR_FILEERROR = '424' +ERR_NONICKNAMEGIVEN = '431' +ERR_ERRONEUSNICKNAME = '432' +ERR_NICKNAMEINUSE = '433' +ERR_NICKCOLLISION = '436' +ERR_USERNOTINCHANNEL = '441' +ERR_NOTONCHANNEL = '442' +ERR_USERONCHANNEL = '443' +ERR_NOLOGIN = '444' +ERR_SUMMONDISABLED = '445' +ERR_USERSDISABLED = '446' +ERR_NOTREGISTERED = '451' +ERR_NEEDMOREPARAMS = '461' +ERR_ALREADYREGISTRED = '462' +ERR_NOPERMFORHOST = '463' +ERR_PASSWDMISMATCH = '464' +ERR_YOUREBANNEDCREEP = '465' +ERR_KEYSET = '467' +ERR_CHANNELISFULL = '471' +ERR_UNKNOWNMODE = '472' +ERR_INVITEONLYCHAN = '473' +ERR_BANNEDFROMCHAN = '474' +ERR_BADCHANNELKEY = '475' +ERR_BADCHANMASK = '476' +ERR_BANLISTFULL = '478' +ERR_NOPRIVILEGES = '481' +ERR_CHANOPRIVSNEEDED = '482' +ERR_CANTKILLSERVER = '483' +ERR_UNIQOPRIVSNEEDED = '485' +ERR_NOOPERHOST = '491' +ERR_UMODEUNKNOWNFLAG = '501' +ERR_USERSDONTMATCH = '502' \ No newline at end of file diff --git a/dickserv/core/database.py b/dickserv/core/database.py new file mode 100644 index 0000000..87e4593 --- /dev/null +++ b/dickserv/core/database.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# database.py + +import os +import sqlite3 + +# Globals +db = sqlite3.connect(os.path.join('data', 'bot.db'), check_same_thread=False) +sql = db.cursor() + +def check(): + tables = sql.execute('SELECT name FROM sqlite_master WHERE type=\'table\'').fetchall() + if not len(tables): + sql.execute('CREATE TABLE IGNORE (IDENT TEXT NOT NULL);') + sql.execute('CREATE TABLE SETTINGS (SETTING TEXT NOT NULL, VALUE INTEGER NOT NULL);') + sql.execute('INSERT INTO SETTINGS (SETTING,VALUE) VALUES (?, ?)', ('max_results', 5)) + sql.execute('INSERT INTO SETTINGS (SETTING,VALUE) VALUES (?, ?)', ('max_todo', 100)) + sql.execute('INSERT INTO SETTINGS (SETTING,VALUE) VALUES (?, ?)', ('max_todo_per', 5)) + sql.execute('INSERT INTO SETTINGS (SETTING,VALUE) VALUES (?, ?)', ('todo_expire', 7)) + sql.execute('CREATE TABLE TODO (DATE TEXT NOT NULL, IDENT TEXT NOT NULL, DATA TEXT NOT NULL);') + db.commit() + +class Ignore: + def add(ident): + sql.execute('INSERT INTO IGNORE (IDENT) VALUES (?)', (ident,)) + db.commit() + + def idents(): + return list(item[0] for item in sql.execute('SELECT IDENT FROM IGNORE ORDER BY IDENT ASC').fetchall()) + + def remove(ident): + sql.execute('DELETE FROM IGNORE WHERE IDENT=?', (ident,)) + db.commit() + + def reset(): + sql.execute('DROP TABLE IGNORE') + sql.execute('CREATE TABLE IGNORE (IDENT TEXT NOT NULL);') + db.commit() + +class Settings: + def get(setting): + return sql.execute('SELECT VALUE FROM SETTINGS WHERE SETTING=?', (setting,)).fetchone()[0] + + def read(): + return sql.execute('SELECT SETTING,VALUE FROM SETTINGS ORDER BY SETTING ASC').fetchall() + + def settings(): + return list(item[0] for item in sql.execute('SELECT SETTING FROM SETTINGS').fetchall()) + + def update(setting, value): + sql.execute('UPDATE SETTINGS SET VALUE=? WHERE SETTING=?', (value, setting)) + db.commit() + +class Todo: + def add(date, ident, data): + sql.execute('INSERT INTO TODO (DATE,IDENT,DATA) VALUES (?,?,?)', (date, ident, data)) + db.commit() + + def expire_check(): + todos = set(list(item[0] for item in sql.execute('SELECT DATE FROM TODO').fetchall())) + for date in todos: + if functions.timespan(date) > Settings.get('todo_expire'): + sql.execute('DELETE FROM TODO WHERE DATE=?', (date,)) + db.commit() + + def idents(): + return list(item[0] for item in sql.execute('SELECT IDENT FROM TODO').fetchall()) + + def read(ident=None): + if ident: + return list(item[0] for item in sql.execute('SELECT DATA FROM TODO WHERE IDENT=?', (ident,)).fetchall()) + else: + return sql.execute('SELECT DATE,IDENT,DATA FROM TODO ORDER BY DATE ASC, IDENT ASC, DATA ASC').fetchall() + + def remove(ident, data): + sql.execute('DELETE FROM TODO WHERE IDENT=? AND DATA=?', (ident, data)) + db.commit() + + def reset(): + sql.execute('DROP TABLE TODO') + sql.execute('CREATE TABLE TODO (DATE TEXT NOT NULL, IDENT TEXT NOT NULL, DATA TEXT NOT NULL);') + db.commit() \ No newline at end of file diff --git a/dickserv/core/debug.py b/dickserv/core/debug.py new file mode 100644 index 0000000..a178193 --- /dev/null +++ b/dickserv/core/debug.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# debug.py + +import ctypes +import logging +import os +import sys +import time + +from logging.handlers import RotatingFileHandler + +import config + +def check_libs(): + if config.connection.proxy: + try: + import socks + except ImportError: + error_exit('Missing \'socks\' module! (https://pypi.python.org/pypi/PySocks)') + try: + import bs4 + except ImportError: + error_exit('Missing \'bs4\' module. (https://pypi.python.org/pypi/beautifulsoup4)') + try: + import googleapiclient.discovery + except ImportError: + error_exit('Missing \'google-api-python-client\' module. (https://pypi.python.org/pypi/google-api-python-client/)') + + +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: + logging.debug(f'[!] - {msg} ({reason})') + else: + logging.debug('[!] - ' + msg) + +def error_exit(msg): + raise SystemExit('[!] - ' + msg) + +def info(): + clear() + logging.debug('#'*56) + logging.debug('#{0}#'.format(''.center(54))) + logging.debug('#{0}#'.format('DickServ IRC'.center(54))) + logging.debug('#{0}#'.format('Developed by acidvegas in Python'.center(54))) + logging.debug('#{0}#'.format('https://acid.vegas/dickserv'.center(54))) + logging.debug('#{0}#'.format(''.center(54))) + logging.debug('#'*56) + +def irc(msg): + logging.debug('[~] - ' + msg) + +def setup_logger(): + stream_handler = logging.StreamHandler(sys.stdout) + if config.settings.log: + log_file = os.path.join(os.path.join('data','logs'), 'bot.log') + file_handler = RotatingFileHandler(log_file, maxBytes=256000, backupCount=3) + logging.basicConfig(level=logging.NOTSET, format='%(asctime)s | %(message)s', datefmt='%I:%M:%S', handlers=(file_handler,stream_handler)) + else: + logging.basicConfig(level=logging.NOTSET, format='%(asctime)s | %(message)s', datefmt='%I:%M:%S', handlers=(stream_handler,)) \ No newline at end of file diff --git a/dickserv/core/functions.py b/dickserv/core/functions.py new file mode 100644 index 0000000..c041c03 --- /dev/null +++ b/dickserv/core/functions.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# functions.py + +import datetime +import random +import re +import time + +def between(source, start, stop): + data = re.compile(start + '(.*?)' + stop, re.IGNORECASE|re.MULTILINE).search(source) + if data: + return data.group(1) + else: + return False + +def current_date(): + return time.strftime('%A, %B %d, %Y - %I:%M %p') + +def floatint(data): + if data.isdigit(): + return int(data) + else: + return float(data) + +def get_date(): + return datetime.date.today().strftime('%m/%d/%Y') + +def get_datetime(data): + return datetime.datetime.strptime(data, '%m/%d/%Y') + +def luck(odds): + if random_int(1,odds) == 1: + return True + else: + return False + +def random_int(min, max): + return random.randint(min, max) + +def timespan(date): + delta = datetime.date(get_date()) - datetime.date(get_datetime(date)) + return delta.days + +def trim(data, max_length): + if len(data) > max_length: + return data[:max_length] + '...' + else: + return data + +def uptime(start_time): + uptime = datetime.datetime(1,1,1) + datetime.timedelta(seconds=time.time() - start_time) + return f'{uptime.day-1} Days, {uptime.hour} Hours, {uptime.minute} Minutes, {uptime.second} Seconds' \ No newline at end of file diff --git a/dickserv/core/httplib.py b/dickserv/core/httplib.py new file mode 100644 index 0000000..4c27ad1 --- /dev/null +++ b/dickserv/core/httplib.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# httplib.py + +import json +import os +import re +import urllib.parse +import urllib.request + +from bs4 import BeautifulSoup + +def clean_url(url): + for prefix in ('https://', 'http://', 'www.'): + if url.startswith(prefix): + url = url[len(prefix):] + if url[-1:] == '/': + url = url[:-1] + return url + +def data_quote(data): + return urllib.parse.quote(data) + +def data_encode(data): + return urllib.parse.urlencode(data) + +def get_file(url): + return os.path.basename(url) + +def get_json(url): + return json.loads(get_source(url)) + +def get_size(url): + content_length = int(get_url(url).getheader('content-length')) + for unit in ('B','KB','MB','GB','TB','PB','EB','ZB'): + if abs(content_length) < 1024.0: + return '{0:.2f}'.format(content_length) + unit + content_length /= 1024.0 + return '{0:.2f}'.format(content_length) + 'YB' + +def get_source(url): + source = get_url(url) + charset = source.headers.get_content_charset() + if charset: + return source.read().decode(charset) + else: + return source.read().decode() + +def get_title(url): + source = get_source(url) + soup = BeautifulSoup(source, 'html.parser') + return ' '.join(soup.title.string.split()) + +def get_type(url): + return get_url(url).info().get_content_type() + +def get_url(url): + req = urllib.request.Request(url) + req.add_header('User-Agent', 'DickServ/1.0') + return urllib.request.urlopen(req, timeout=10) + +def parse_urls(data): + return re.compile('(?:http[s]?:\/\/|www.)(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', re.IGNORECASE).findall(data) diff --git a/dickserv/core/irc.py b/dickserv/core/irc.py new file mode 100644 index 0000000..c7d4bb3 --- /dev/null +++ b/dickserv/core/irc.py @@ -0,0 +1,479 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# irc.py + +import socket +import time + +import config +import constants +import database +import debug +import functions +import httplib + +from commands import * + +# Load optional modules +if config.connection.ssl: + import ssl +if config.connection.proxy: + import sock + +def color(msg, foreground, background=None): + if foreground == 'random': + foreground = '{0:0>2}'.format(functions.random_int(2,13)) + if background == 'random': + background = '{0:0>2}'.format(functions.random_int(2,13)) + if background: + return f'\x03{foreground},{background}{msg}{constants.reset}' + else: + return f'\x03{foreground}{msg}{constants.reset}' + +class IRC(object): + def __init__(self): + self.last = 0 + self.slow = False + self.sock = None + self.start = 0 + self.status = True + + def connect(self): + try: + self.create_socket() + self.sock.connect((config.connection.server, config.connection.port)) + self.register() + except socket.error as ex: + debug.error('Failed to connect to IRC server.', ex) + Events.disconnect() + else: + self.listen() + + def create_socket(self): + family = socket.AF_INET6 if config.connection.ipv6 else socket.AF_INET + if config.connection.proxy: + proxy_server, proxy_port = config.connection.proxy.split(':') + self.sock = socks.socksocket(family, socket.SOCK_STREAM) + self.sock.setblocking(0) + self.sock.settimeout(15) + self.sock.setproxy(socks.PROXY_TYPE_SOCKS5, proxy_server, int(proxy_port)) + else: + self.sock = socket.socket(family, socket.SOCK_STREAM) + if config.connection.vhost: + self.sock.bind((config.connection.vhost, 0)) + if config.connection.ssl: + ctx = ssl.SSLContext() + if config.cert.file: + ctx.load_cert_chain(config.cert.file, config.cert.key, config.cert.password) + if config.connection.ssl_verify: + ctx.verify_mode = ssl.CERT_REQUIRED + ctx.load_default_certs() + else: + ctx.check_hostname = False + ctx.verify_mode = ssl.CERT_NONE + self.sock = ctx.wrap_socket(self.sock) + + def listen(self): + while True: + try: + data = self.sock.recv(1024).decode('utf-8') + for line in (line for line in data.split('\r\n') if line): + debug.irc(line) + if len(line.split()) >= 2: + Events.handle(line) + except (UnicodeDecodeError,UnicodeEncodeError): + pass + except Exception as ex: + debug.error('Unexpected error occured.', ex) + break + Events.disconnect() + + def register(self): + if config.login.network: + Commands.raw('PASS ' + config.login.network) + Commands.raw(f'USER {config.ident.username} 0 * :{config.ident.realname}') + Commands.nick(config.ident.nickname) + + + +class Commands: + def action(chan, msg): + Commands.sendmsg(chan, f'\x01ACTION {msg}\x01') + + def error(target, data, reason=None): + if reason: + Commands.sendmsg(target, '[{0}] {1} {2}'.format(color('!', constants.red), data, color('({0})'.format(reason), constants.grey))) + else: + Commands.sendmsg(target, '[{0}] {1}'.format(color('!', constants.red), data)) + + def identify(nick, password): + Commands.sendmsg('nickserv', f'identify {nick} {password}') + + def join_channel(chan, key=None): + Commands.raw(f'JOIN {chan} {key}') if key else Commands.raw('JOIN ' + chan) + + def mode(target, mode): + Commands.raw(f'MODE {target} {mode}') + + def nick(nick): + Commands.raw('NICK ' + nick) + + def notice(target, msg): + Commands.raw(f'NOTICE {target} :{msg}') + + def oper(user, password): + Commands.raw(f'OPER {user} {password}') + + def raw(msg): + msg = msg.replace('\r','').replace('\n','')[:450] + DickServ.sock.send(bytes(msg + '\r\n', 'utf-8')) + + def sendmsg(target, msg): + Commands.raw(f'PRIVMSG {target} :{msg}') + + + +class Events: + def connect(): + DickServ.start = time.time() + if config.settings.modes: + Commands.mode(config.ident.nickname, '+' + config.settings.modes) + if config.login.nickserv: + Commands.identify(config.ident.nickname, config.login.nickserv) + if config.login.operator: + Commands.oper(config.ident.username, config.login.operator) + Commands.join_channel(config.connection.channel, config.connection.key) + + def disconnect(): + DickServ.sock.close() + time.sleep(10) + DickServ.connect() + + def kick(nick, chan, kicked): + if kicked == config.ident.nickname and chan == config.connection.channel: + time.sleep(3) + Commands.join_channel(chan, config.connection.key) + + def message(nick, ident, chan, msg): + try: + if chan == config.connection.channel and (DickServ.status or ident == config.settings.admin): + if not msg.startswith(config.settings.cmd_char): + urls = httplib.parse_urls(msg) + if urls: + if time.time() - DickServ.last > 3: + DickServ.last = time.time() + Events.url(chan, urls[0]) + elif msg == '@dickserv': + Commands.sendmsg(chan, constants.bold + 'DickServ IRC Bot - Developed by acidvegas in Python - https://acid.vegas/dickserv') + elif msg == '@dickserv help': + Commands.sendmsg(chan, 'https://git.supernets.org/acidvegas/dickserv#commands') + elif msg == 'h' and functions.luck(4): + Commands.sendmsg(chan, 'h') + elif 'qhat' in msg: + Commands.sendmsg(chan, 'Q:)') + elif ident not in database.Ignore.idents(): + if time.time() - DickServ.last < 3 and ident != config.settings.admin: + if not DickServ.slow: + Commands.sendmsg(chan, color('Slow down nerd!', constants.red)) + DickServ.slow = True + else: + DickServ.slow = False + args = msg.split() + argz = msg[len(args[0])+1:] + cmd = args[0][1:] + if len(args) == 1: + if cmd == 'date': + Commands.sendmsg(chan, functions.current_date()) + elif cmd == 'talent': + if functions.luck(1000): + Commands.sendmsg(chan, color(f' !!! HOLY FUCKING SHIT {nick} ACHIEVED TALENT !!! ', 'random', 'random')) + Commands.sendmsg(chan, color(' !!! RIP DITTLE DIP DIP DIP DIP IT\'S YOUR BIRTHDAY !!! ', 'random', 'random')) + Commands.sendmsg(chan, color(f' !!! CAN WE HAVE A GOT DAMN MOMENT OF SILENCE FOR {nick} :) !!! ', 'random', 'random')) + Commands.sendmsg(chan, color(' !!! GOT DAMN XD THIS IS TOO CRAZY LIKE...DAMN HAHA. DAMN. !!! ', 'random', 'random')) + else: + Commands.sendmsg(chan, color('(^)', 'random')) + elif cmd == 'todo': + todos = database.Todo.read(ident) + if todos: + for item in todos: + Commands.notice(nick, '[{0}] {1}'.format(color(todos.index(item)+1, constants.pink), item)) + else: + Commands.notice(nick, 'You have no saved todos.') + elif cmd == 'uptime': + Commands.sendmsg(chan, functions.uptime(DickServ.start)) + elif len(args) == 2: + if cmd == 'coin': + api = cryptocurrency.get(args[1]) + if api: + Commands.sendmsg(chan, '{0} {1} - ${2:,.2f}'.format(color(api['name'], constants.white), color('({0})'.format(api['symbol']), constants.grey), float(api['price_usd']))) + else: + Commands.error(chan, 'Invalid cryptocurrency name!') + elif cmd == 'drug': + api = tripsit.drug(args[1]) + if api: + Commands.sendmsg(chan, '{0} - {1}'.format(color(api['name'], constants.yellow), api['desc'])) + else: + Commands.error(chan, 'No results found.') + elif cmd == 'define': + definition = dictionary.define(args[1]) + if definition: + Commands.sendmsg(chan, '{0} - {1}: {2}'.format(color('Definition', constants.white, constants.blue), args[1].lower(), definition)) + else: + Commands.error(chan, 'No results found.') + elif cmd == 'isup': + Commands.sendmsg(chan, '{0} is {1}'.format(args[1], isup.check(args[1]))) + elif cmd == 'r': + api = reddit.read(args[1]) + if api: + data = list(api.keys()) + for i in data: + count = str(data.index(i)+1) + Commands.sendmsg(chan, '[{0}] {1} [{2}|{3}/{4}|{5}]'.format(color(count, constants.pink), functions.trim(i, 100), color(str(api[i]['score']), constants.white), color('+' + str(api[i]['ups']), constants.green), color('-' + str(api[i]['downs']), constants.red), color(api[i]['comments'], constants.white))) + Commands.sendmsg(chan, ' - ' + color(api[i]['url'], constants.grey)) + else: + Commands.error(chan, 'No results found.') + elif cmd == 'w': + if args[1].isdigit(): + api = weather.lookup(args[1]) + if api: + Commands.sendmsg(chan, api) + else: + Commands.error(chan, 'No results found.') + else: + Commands.error(chan, 'Invalid arguments.') + if len(args) >= 2: + if cmd == 'g': + api = google.search(argz, database.Settings.get('max_results')) + if api: + for result in api: + count = api.index(result)+1 + Commands.sendmsg(chan, '[{0}] {1}'.format(color(count, constants.pink), result['title'])) + Commands.sendmsg(chan, ' - ' + color(result['link'], constants.grey)) + else: + Commands.error(chan, 'No results found.') + elif cmd == 'imdb': + api = imdb.search(argz) + if api: + Commands.sendmsg(chan, '{0} {1} {2} {3}'.format(color('Title :', constants.white), api['Title'], api['Year'], color(api['Rated'], constants.grey))) + Commands.sendmsg(chan, '{0} {1}{2}'.format(color('Link :', constants.white), constants.underline, color('https://imdb.com/title/' + api['imdbID'], constants.light_blue))) + Commands.sendmsg(chan, '{0} {1}'.format(color('Genre :', constants.white), api['Genre'])) + if api['imdbRating'] == 'N/A': + Commands.sendmsg(chan, '{0} {1} 0/10'.format(color('Rating :', constants.white), color('★★★★★★★★★★', constants.grey))) + else: + Commands.sendmsg(chan, '{0} {1}{2} {3}/10'.format(color('Rating :', constants.white), color('★'*round(float(api['imdbRating'])), constants.yellow), color('★'*(10-round(float(api['imdbRating']))), constants.grey), api['imdbRating'])) + Commands.sendmsg(chan, '{0} {1}'.format(color('Plot :', constants.white), api['Plot'])) + else: + Commands.error(chan, 'No results found.') + elif cmd == 'netsplit': + api = netsplit.search(argz) + if api: + data = list(api.keys()) + for i in data: + count = str(data.index(i)+1) + Commands.sendmsg(chan, '[{0}] {1} {2} / {3}'.format(color(count, constants.pink), color(i, constants.light_blue), color('({0})'.format(api[i]['users']), constants.grey), color(api[i]['network'], constants.red))) + Commands.sendmsg(chan, color(' - ' + api[i]['topic'], constants.grey)) + else: + Commands.error(chan, 'No results found.') + elif cmd == 'todo' and len(args) >= 3: + if len(args) >= 3 and args[1] == 'add': + todos = database.Todo.read(ident) + if len(todos) <= database.Settings.get('max_todo_per') and len(database.Todo.read()) <= database.Settings.get('max_todo'): + argz = argz[4:] + if argz not in todos: + database.Todo.add(functions.get_date(), ident, argz) + Commands.notice(nick, 'Todo added to database!') + else: + Commands.notice(nick, 'Todo already in database!') + else: + Commands.notice(nick, 'Maximum todos reached!') + elif len(args) == 3 and args[1] == 'del': + num = args[2] + if num.isdigit(): + num = int(num) + todos = database.Todo.read(ident) + if todos: + if num <= len(todos): + for item in todos: + count = todos.index(item)+1 + if count == num: + database.Todo.remove(ident, item) + break + Commands.notice(nick, 'Todo removed from database!') + else: + Commands.notice(nick, 'Invalid number.') + else: + Commands.notice(nick, 'No todos found.') + else: + Commands.notice(nick, 'Invalid number.') + else: + Commands.notice(nick, 'Invalid arguments.') + elif cmd == 'tpb': + api = tpb.search(argz, database.Settings.get('max_results')) + if api: + data = list(api.keys()) + for i in data: + count = str(data.index(i)+1) + Commands.sendmsg(chan, '[{0}] {1} [{2}/{3}]'.format(color(count, constants.pink), i, color(api[i]['seeders'], constants.green), color(api[i]['leechers'], constants.red))) + Commands.sendmsg(chan, ' - ' + color('http://thepiratebay.org' + api[i]['url'], constants.grey)) + else: + Commands.error(chan, 'No results found.') + elif cmd == 'ud': + definition = dictionary.urban(argz) + if definition: + Commands.sendmsg(chan, '{0}{1} - {2}: {3}'.format(color('urban', constants.white, constants.blue), color('DICTIONARY', constants.yellow, constants.black), argz, definition)) + else: + Commands.error(chan, 'No results found.') + elif cmd == 'wolfram': + results = wolfram.ask(argz) + if results: + Commands.sendmsg(chan, '{0}{1} - {2}'.format(color('Wolfram', constants.red), color('Alpha', constants.orange), results)) + else: + Commands.error(chan, 'No results found.') + elif cmd == 'yt': + api = youtube.search(argz, database.Settings.get('max_results')) + if api: + data = list(api.keys()) + for i in api.keys(): + count = str(data.index(i)+1) + Commands.sendmsg(chan, '[{0}] {1}'.format(color(count, constants.pink), functions.trim(i, 75))) + Commands.sendmsg(chan, ' - ' + color(api[i], constants.grey)) + else: + Commands.error(chan, 'No results found.') + DickServ.last = time.time() + except Exception as ex: + Commands.error(chan, 'Command threw an exception.', ex) + + def nick_in_use(): + debug.error('DickServ is already running or nick is in use.') + + def private(nick, ident, msg): + try: + if ident == config.settings.admin_host: + args = msg.split() + cmd = args[0][1:] + if len(args) == 1: + if cmd == 'config': + settings = database.Settings.read() + Commands.sendmsg(nick, '[{0}]'.format(color('Settings', constants.purple))) + for setting in settings: + Commands.sendmsg(nick, '{0} = {1}'.format(color(setting[0], constants.yellow), color(setting[1], constants.grey))) + elif cmd == 'ignore': + ignores = database.Ignore.idents() + if ignores: + Commands.sendmsg(nick, '[{0}]'.format(color('Ignore List', constants.purple))) + for user in ignores: + Commands.sendmsg(nick, color(user, constants.yellow)) + Commands.sendmsg(nick, '{0} {1}'.format(color('Total:', constants.light_blue), color(len(ignores), constants.grey))) + else: + Commands.error(nick, 'Ignore list is empty!') + elif cmd == 'off': + DickServ.status = False + Commands.sendmsg(nick, color('OFF', constants.red)) + elif cmd == 'on': + DickServ.status = True + Commands.sendmsg(nick, color('ON', constants.green)) + elif len(args) == 2: + if cmd == 'ignore' and args[1] == 'reset': + database.Ignore.reset() + elif cmd == 'todo' and args[1] == 'expire': + database.Todo.expire_check() + elif cmd == 'todo' and args[1] == 'reset': + database.Todo.reset() + elif len(args) == 3: + if cmd == 'config': + setting, value = args[1], args[2] + if functions.CheckString.number(value): + value = functions.floatint(value) + if value >= 0: + if setting in database.Settings.settings(): + database.Settings.update(setting, value) + Commands.sendmsg(nick, 'Change setting for {0} to {1}.'.format(color(setting, constants.yellow), color(value, constants.grey))) + else: + Commands.error(nick, 'Invalid config variable.') + else: + Commands.error(nick, 'Value must be greater than or equal to zero.') + else: + Commands.error(nick, 'Value must be an integer or float.') + elif cmd == 'ignore': + if args[1] == 'add': + user_ident = args[2] + if user_ident not in database.Ignore.idents(): + database.Ignore.add(nickname, user_ident) + Commands.sendmsg(nick, 'Ident {0} to the ignore list.'.format(color('added', constants.green))) + else: + Commands.error(nick, 'Ident is already on the ignore list.') + elif cmd == 'del': + user_ident = args[2] + if user_ident in database.Ignore.idents(): + database.Ignore.remove(user_ident) + Commands.sendmsg(nick, 'Ident {0} from the ignore list.'.format(color('removed', constants.red))) + else: + Commands.error(nick, 'Ident does not exist in the ignore list.') + except Exception as ex: + Commands.error(nick, 'Command threw an exception.', ex) + + def url(chan, url): + try: + if imdb.check(url): + id = imdb.check(url) + api = imdb.search(id) + if api: + Commands.sendmsg(chan, '{0} {1} {2} {3}'.format(color('Title :', constants.white), api['Title'], api['Year'], color(api['Rated'], constants.grey))) + Commands.sendmsg(chan, '{0} {1}{2}'.format(color('Link :', constants.white), constants.underline, color('https://imdb.com/title/' + api['imdbID'], constants.light_blue))) + Commands.sendmsg(chan, '{0} {1}'.format(color('Genre :', constants.white), api['Genre'])) + if api['imdbRating'] == 'N/A': + Commands.sendmsg(chan, '{0} {1} 0/10'.format(color('Rating :', constants.white), color('★★★★★★★★★★', constants.grey))) + else: + Commands.sendmsg(chan, '{0} {1}{2} {3}/10'.format(color('Rating :', constants.white), color('★'*round(float(api['imdbRating'])), constants.yellow), color('★'*(10-round(float(api['imdbRating']))), constants.grey), api['imdbRating'])) + Commands.sendmsg(chan, '{0} {1}'.format(color('Plot :', constants.white), api['Plot'])) + elif reddit.check(url): + subreddit = reddit.check(url)[0] + post_id = reddit.check(url)[1] + api = reddit.post_info(subreddit, post_id) + if api: + Commands.sendmsg(chan, '[{0}] - {1} [{2}|{3}/{4}|{5}]'.format(color('reddit', constants.cyan), color(functions.trim(api['title'], 75), constants.white), color(api['score'], constants.white), color('+' + api['ups'], constants.green), color('-' + api['downs'], constants.red), color(api['num_comments'], constants.white))) + elif youtube.check(url): + api = youtube.video_info(youtube.check(url)) + if api: + Commands.sendmsg(chan, '{0}{1} - {2} [{3}|{4}/{5}]'.format(color('You', constants.black, constants.white), color('Tube', constants.white, constants.red), functions.trim(api['title'], 75), color(api['views'], constants.white), color('+' + api['likes'], constants.green), color('-' + api['dislikes'], constants.red))) + Commands.sendmsg(chan, color(api['description'], constants.grey)) + else: + url_type = httplib.get_type(url) + if url_type == 'text/html': + title = httplib.get_title(url) + Commands.sendmsg(chan, '[{0}] {1}'.format(color(url_type, constants.pink), color(title, constants.white))) + else: + file_name = httplib.get_file(url) + if file_name: + file_size = httplib.get_size(url) + Commands.sendmsg(chan, '[{0}] {1} [{2}]'.format(color(url_type, constants.pink), color(file_name, constants.white), color(file_size, constants.blue))) + except Exception as ex: + debug.error('Title Error', ex) + + def handle(data): + args = data.split() + if data.startswith('ERROR :Closing Link:'): + raise Exception('Connection has closed.') + elif args[0] == 'PING': + Commands.raw('PONG ' + args[1][1:]) + elif args[1] == constants.RPL_WELCOME: + Events.connect() + elif args[1] == constants.ERR_NICKNAMEINUSE: + Events.nick_in_use() + elif args[1] == constants.KICK: + nick = args[0].split('!')[0][1:] + chan = args[2] + kicked = args[3] + Events.kick(nick, chan, kicked) + elif args[1] == constants.PRIVMSG: + nick = args[0].split('!')[0][1:] + ident = args[0].split('!')[1] + chan = args[2] + msg = ' '.join(args[3:])[1:] + if chan == config.ident.nickname: + Events.private(nick, ident, msg) + else: + Events.message(nick, ident, chan, msg) + +DickServ = IRC() diff --git a/dickserv/data/cert/.gitignore b/dickserv/data/cert/.gitignore new file mode 100644 index 0000000..86d0cb2 --- /dev/null +++ b/dickserv/data/cert/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/dickserv/data/logs/.gitignore b/dickserv/data/logs/.gitignore new file mode 100644 index 0000000..86d0cb2 --- /dev/null +++ b/dickserv/data/logs/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/dickserv/dickserv.py b/dickserv/dickserv.py new file mode 100644 index 0000000..85d2b69 --- /dev/null +++ b/dickserv/dickserv.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# dickserv.py + +import os +import sys + +sys.dont_write_bytecode = True +os.chdir(sys.path[0] or '.') +sys.path += ('core','modules') + +import debug + +debug.setup_logger() +debug.info() +if not debug.check_version(3): + debug.error_exit('Python 3 is required!') +if debug.check_privileges(): + debug.error_exit('Do not run as admin/root!') +debug.check_libs() +import database +database.check() +import irc +irc.DickServ.connect() \ No newline at end of file diff --git a/dickserv/modules/cryptocurrency.py b/dickserv/modules/cryptocurrency.py new file mode 100644 index 0000000..5ed85ce --- /dev/null +++ b/dickserv/modules/cryptocurrency.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# cryptocurrency.py + +import httplib + +def get(coin): + api = httplib.get_json('https://api.coinmarketcap.com/v1/ticker/?limit=500') + data = [item for item in api if (coin.lower() == item['id'] or coin.upper() == item['symbol'])] + if data: + return data[0] + else: + return False \ No newline at end of file diff --git a/dickserv/modules/dictionary.py b/dickserv/modules/dictionary.py new file mode 100644 index 0000000..0359e4c --- /dev/null +++ b/dickserv/modules/dictionary.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# dictionary.py + +import httplib +import functions + +def define(word): + source = httplib.get_source('http://www.merriam-webster.com/dictionary/' + word.replace(' ', '%20')) + results = functions.between(source, f'') + if results: + return results + else: + return False + +def urban(word): + api = httplib.get_json('http://api.urbandictionary.com/v0/define?term=' + word.replace(' ', '+')) + if api['result_type'] != 'no_results': + definition = api['list'][0]['definition'] + return definition + else: + return False diff --git a/dickserv/modules/google.py b/dickserv/modules/google.py new file mode 100644 index 0000000..2aefb0f --- /dev/null +++ b/dickserv/modules/google.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# google.py + +from googleapiclient.discovery import build + +import config + +def search(query, results): + service = build('customsearch', 'v1', developerKey=config.api.google_api_key, cache_discovery=False) + results = service.cse().list(q=query, cx=config.api.google_cse_id, num=results).execute() + return results['items'] \ No newline at end of file diff --git a/dickserv/modules/imdb.py b/dickserv/modules/imdb.py new file mode 100644 index 0000000..43325aa --- /dev/null +++ b/dickserv/modules/imdb.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# imdb.py + +import re + +import config +import httplib + +def check(url): + found = re.match('^.*?imdb.com\/title\/tt([0-9A-Za-z]+).*?$', url, re.IGNORECASE) + if found: + return found.group(1) + else: + return False + +def search(query): + if query.startswith('tt') and len(query) == 9: + api = httplib.get_json(f'http://omdbapi.com/?i={query}&apikey={config.api.omdbapi_key}') + else: + year = query.split()[-1] + if len(year) == 4 and year.isdigit(): + query = query[:-5].replace(' ', '%20') + api = httplib.get_json(f'http://omdbapi.com/?t={query}&y={year}&apikey={config.api.omdbapi_key}') + else: + query = query.replace(' ', '%20') + api = httplib.get_json(f'http://omdbapi.com/?t={query}&apikey={config.api.omdbapi_key}') + if api['Response'] == 'True': + return api + else: + return False \ No newline at end of file diff --git a/dickserv/modules/isup.py b/dickserv/modules/isup.py new file mode 100644 index 0000000..0d4e7cd --- /dev/null +++ b/dickserv/modules/isup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# isup.py + +import httplib + +def check(url): + source = httplib.get_source('http://isup.me/' + url) + if source.find('It\'s just you.') != -1: + return 'UP' + elif source.find('It\'s not just you!') != -1: + return 'DOWN' + elif source.find('Huh?') != -1: + return 'INVALID' + else: + return 'UNKNOWN' diff --git a/dickserv/modules/netsplit.py b/dickserv/modules/netsplit.py new file mode 100644 index 0000000..855f5a6 --- /dev/null +++ b/dickserv/modules/netsplit.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# netsplit.py + +import re + +import functions +import httplib + +def search(query): + channels = {} + source = httplib.get_source('http://irc.netsplit.de/channels/?chat=' + query.replace(' ','+')) + for i in ('​','','','','',''): + source = source.replace(i, '') + channel_objects = re.findall('
(.*?)
', source, re.IGNORECASE|re.MULTILINE) + for data in channel_objects: + channel = functions.between(data, '', '') + network = functions.between(data, '', '') + users = functions.between(data, '', ' – ') + topic = functions.between(data, '', '
') + if not topic: + topic = 'No channel topic set.' + channels[channel] = {'network':network,'users':users,'topic':topic} + return channels \ No newline at end of file diff --git a/dickserv/modules/reddit.py b/dickserv/modules/reddit.py new file mode 100644 index 0000000..8afd0a9 --- /dev/null +++ b/dickserv/modules/reddit.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# reddit.py + +import re + +import httplib +from database import Settings + +def check(url): + found = re.match('^.*?reddit.com\/r\/(.*?)\/comments\/([0-9A-Za-z]+).*$', url, re.IGNORECASE) + if found: + return (found.group(1), found.group(2)) + else: + return False + +def post_info(subreddit, id): + api = httplib.get_json(f'https://www.reddit.com/r/{subreddit}/comments/{id}.json') + if 'error' not in api: + return api[0]['data']['children'][0]['data'] + else: + return False + +def read(subreddit): + api = httplib.get_json('https://www.reddit.com/r/{0}.json?limit={1}'.format(subreddit, Settings.get('max_results'))) + data = [x['data'] for x in api['data']['children']] + if data: + results = {} + for item in data: + if not item['stickied']: + results[item['title']] = {'url':item['url'], 'score':item['score'], 'ups':item['ups'], 'downs':item['downs'], 'comments':item['num_comments']} + return results + else: + return False diff --git a/dickserv/modules/tpb.py b/dickserv/modules/tpb.py new file mode 100644 index 0000000..67e626f --- /dev/null +++ b/dickserv/modules/tpb.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# tpb.py + +import re + +import httplib +from database import Settings + +def search(query, results): + url = 'https://thepiratebay.org/search/{0}/0/99/0'.format(query.replace(' ', '+')) + source = httplib.get_source(url) + torrents = re.findall('(.*?)', source) + seeders = re.findall('\t\t\n\t\t(.*?)', source) + leechers = re.findall('(.*?)\n\t', source) + if torrents: + data = {} + torrents = torrents[:results] + for i in range(len(torrents)): + data[torrents[i][1]] = {'seeders':seeders[i], 'leechers':leechers[i], 'url':torrents[i][0]} + return data + else: + return False \ No newline at end of file diff --git a/dickserv/modules/tripsit.py b/dickserv/modules/tripsit.py new file mode 100644 index 0000000..f0f1c80 --- /dev/null +++ b/dickserv/modules/tripsit.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# tripsit.py + +import httplib + +def drug(query): + api = httplib.get_json('http://tripbot.tripsit.me/api/tripsit/getDrug?name=' + query.replace(' ','%20')) + if api['err'] != True: + return {'name':api['data'][0]['name'],'desc':api['data'][0]['properties']['summary']} + else: + return False \ No newline at end of file diff --git a/dickserv/modules/weather.py b/dickserv/modules/weather.py new file mode 100644 index 0000000..b07efb2 --- /dev/null +++ b/dickserv/modules/weather.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# weather.py + +import httplib + +import config + +def lookup(zip_code): + api = httplib.get_json('http://api.wunderground.com/api/{0}/conditions/q/{1}.json'.format(config.api.wunderground_api_key, zip_code)) + if 'error' not in api: + city = api['current_observation']['display_location']['city'] + state = api['current_observation']['display_location']['state'] + country = api['current_observation']['display_location']['country'] + weather = api['current_observation']['weather'] + temp = api['current_observation']['temp_f'] + return 'The weather for {0}, {1}, {2} is {3} at {4} F'.format(city, state, country, weather, temp) + else: + return False diff --git a/dickserv/modules/wolfram.py b/dickserv/modules/wolfram.py new file mode 100644 index 0000000..e7a6bc6 --- /dev/null +++ b/dickserv/modules/wolfram.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# wolfram.py + +from xml.etree import ElementTree as etree + +import config +import httplib + +def ask(query): + params = httplib.data_encode({'input':query, 'appid':config.api.wolfram_api_key}) + data = httplib.get_source('http://api.wolframalpha.com/v2/query?' + params) + results = {} + tree = etree.fromstring(data) + for e in tree.findall('pod'): + for item in [ef for ef in list(e) if ef.tag=='subpod']: + for it in [i for i in list(item) if i.tag=='plaintext']: + if it.tag=='plaintext': + results[e.get('title')] = it.text + if 'Result' in results: + return results['Result'] + else: + return False \ No newline at end of file diff --git a/dickserv/modules/youtube.py b/dickserv/modules/youtube.py new file mode 100644 index 0000000..a6edd00 --- /dev/null +++ b/dickserv/modules/youtube.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# DickServ IRC Bot - Developed by acidvegas in Python (https://acid.vegas/dickserv) +# youtube.py + +import re + +import config +import httplib + +def check(url): + found = re.match('^.*?youtu(be)?\.([a-z])+\/(watch(.*?)(\?|\&)v=)?(.*?)(&(.)*)*$', url, re.IGNORECASE) + if found: + return found.group(6) + else: + return False + +def video_info(id): + api = httplib.get_json(f'https://www.googleapis.com/youtube/v3/videos?key={config.api.google_api_key}&part=snippet,statistics&id={id}') + if api['items']: + api = api['items'][0] + data = {} + data['channel'] = api['snippet']['channelTitle'] + data['description'] = ' '.join(api['snippet']['description'].split()) + data['dislikes'] = api['statistics']['dislikeCount'] + data['likes'] = api['statistics']['likeCount'] + data['title'] = api['snippet']['title'] + data['views'] = api['statistics']['viewCount'] + return data + else: + return False + +def search(query, results): + url = 'https://www.googleapis.com/youtube/v3/search?part=snippet&key={0}&q={1}&maxResults={2}&type=video®ionCode=US&relevanceLanguage=en&safeSearch=none'.format(config.api.google_api_key, httplib.data_quote(query), results) + api = httplib.get_json(url) + results = {} + for item in api['items']: + title = item['snippet']['title'] + url = 'https://www.youtube.com/watch?v=' + item['id']['videoId'] + results[title] = url + return results