mirror of
git://git.acid.vegas/dickserv.git
synced 2024-12-26 16:46:38 +00:00
Initial commit
This commit is contained in:
commit
11ceb7fba6
15
LICENSE
Normal file
15
LICENSE
Normal file
@ -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.
|
51
README.md
Normal file
51
README.md
Normal file
@ -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)
|
16
dickserv/core/commands.py
Normal file
16
dickserv/core/commands.py
Normal file
@ -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
|
42
dickserv/core/config.py
Normal file
42
dickserv/core/config.py
Normal file
@ -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/
|
213
dickserv/core/constants.py
Normal file
213
dickserv/core/constants.py
Normal file
@ -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'
|
83
dickserv/core/database.py
Normal file
83
dickserv/core/database.py
Normal file
@ -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()
|
90
dickserv/core/debug.py
Normal file
90
dickserv/core/debug.py
Normal file
@ -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,))
|
53
dickserv/core/functions.py
Normal file
53
dickserv/core/functions.py
Normal file
@ -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'
|
63
dickserv/core/httplib.py
Normal file
63
dickserv/core/httplib.py
Normal file
@ -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)
|
479
dickserv/core/irc.py
Normal file
479
dickserv/core/irc.py
Normal file
@ -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()
|
4
dickserv/data/cert/.gitignore
vendored
Normal file
4
dickserv/data/cert/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
4
dickserv/data/logs/.gitignore
vendored
Normal file
4
dickserv/data/logs/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
24
dickserv/dickserv.py
Normal file
24
dickserv/dickserv.py
Normal file
@ -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()
|
13
dickserv/modules/cryptocurrency.py
Normal file
13
dickserv/modules/cryptocurrency.py
Normal file
@ -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
|
22
dickserv/modules/dictionary.py
Normal file
22
dickserv/modules/dictionary.py
Normal file
@ -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
|
12
dickserv/modules/google.py
Normal file
12
dickserv/modules/google.py
Normal file
@ -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']
|
31
dickserv/modules/imdb.py
Normal file
31
dickserv/modules/imdb.py
Normal file
@ -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
|
16
dickserv/modules/isup.py
Normal file
16
dickserv/modules/isup.py
Normal file
@ -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'
|
24
dickserv/modules/netsplit.py
Normal file
24
dickserv/modules/netsplit.py
Normal file
@ -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
|
34
dickserv/modules/reddit.py
Normal file
34
dickserv/modules/reddit.py
Normal file
@ -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
|
23
dickserv/modules/tpb.py
Normal file
23
dickserv/modules/tpb.py
Normal file
@ -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
|
12
dickserv/modules/tripsit.py
Normal file
12
dickserv/modules/tripsit.py
Normal file
@ -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
|
19
dickserv/modules/weather.py
Normal file
19
dickserv/modules/weather.py
Normal file
@ -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
|
23
dickserv/modules/wolfram.py
Normal file
23
dickserv/modules/wolfram.py
Normal file
@ -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
|
40
dickserv/modules/youtube.py
Normal file
40
dickserv/modules/youtube.py
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user