diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2019, acidvegas <acid.vegas@acid.vegas>
+
+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
@@ -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 \<cryptocurrency> | Get the USD value for \<cryptocurrency>. |
+| date | Get the current date and time. |
+| define \<word> | Get the definition of \<word>. |
+| drug \<query> | Lookup information on \<drug> on tripsit. |
+| g \<query> | Search Google for \<query>. |
+| imdb \<query/ttid> [year] | Search \<query/ttid> on IMDb. |
+| isup \<url> | Check if \<url> is up or not. |
+| netsplit \<query> | Search for \<query> on NetSplit. |
+| r \<subreddit> | Read top posts from \<subreddit> |
+| talent | RIP DITTLE DIP DIP DIP DIP IT\'S YA BIRTHDAY!!1@11! |
+| todo | Read your todo list. |
+| todo add \<data> | Add \<data> to your todo list. |
+| todo del \<num>| | Delete the \<num> todo result. |
+| tpb \<query> | Searc \<query on ThePirateBay. |
+| ud \<word> | Get the urban dictionary definition of \<word>. |
+| uptime | Get the amount of time DickServ has been running. |
+| w \<zip_code> | Get the weather for \<zip>. |
+| wolfram \<ask> | Get the results of \<query> from WolframAlpha. |
+| yt \<query> | Search \<query> on YouTube. |
+
+###### Admin Commands (Private Message)
+| Command | Description |
+| --- | --- |
+| config | View the config settings. |
+| config \<setting> \<value> | Change \<setting> to \<value>. |
+| ignore | View the ignore list. |
+| ignore add \<ident> | Add a user to the ignore list. |
+| ignore del \<ident> | 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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'<meta name="description" content="Define {word}: ', '">')
+ 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
@@ -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
@@ -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
@@ -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
@@ -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 ('​','<b>','</b>','<span style="color:#000000;">','<strong>','</strong>'):
+ source = source.replace(i, '')
+ channel_objects = re.findall('<div style="margin: 4px; padding: 0 0 15 0; text-align: left;">(.*?)</a></span></div>', source, re.IGNORECASE|re.MULTILINE)
+ for data in channel_objects:
+ channel = functions.between(data, '<span class="cs-channel">', '</span>')
+ network = functions.between(data, '<span class="cs-network">', '</span>')
+ users = functions.between(data, '<span class="cs-users">', ' – </span>')
+ topic = functions.between(data, '<span class="cs-topic">', '</span><br>')
+ 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
@@ -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
@@ -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('<a href="(.*?)" class="detLink".*>(.*?)</a>', source)
+ seeders = re.findall('\t\t</td>\n\t\t<td align="right">(.*?)</td>', source)
+ leechers = re.findall('<td align="right">(.*?)</td>\n\t</tr>', 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
@@ -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
@@ -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
@@ -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
@@ -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
| | | | | | | | | | | | | | | | | | | | | | | | |