Finally ready to like add this now oh man this is a huge thing sort of

Added CC-Nanotrasen, an IRC bot made by Skibiliano and given to us by him under CC-BY-SA 3.0 licensing
WHAT DOES THIS MEAN? It means all servers running this SVN now have the option to use an easy to configure IRC bot capable of relaying adminhelps from ingame to the server/channel of their choice.
- Runs on python 2.6 scripts with psyco support
- Relaying can be toggled from config.txt (so you don't runtime with every adminhelp if you decide not to use it)
- Comes with a bunch of other useful and fun tools too
- Added a new global proc, send2irc(msg,msg2) YOU'LL NEVER GUESS WHAT IT DOES CONSIDERING WHAT I JUST MENTIONED
----msg and msg2 are just what text gets relayed to irc, separated by a |, for instance send2irc(hello, world) would come out as
"CC_NanoTrasen: Hello | World


git-svn-id: http://tgstation13.googlecode.com/svn/trunk@2783 316c924e-a436-60f5-8080-3fe189b3f50e
This commit is contained in:
quartz235@gmail.com
2011-12-23 17:39:47 +00:00
parent 240a9bfac5
commit 4472cecbd2
33 changed files with 5954 additions and 2 deletions

View File

@@ -66,4 +66,11 @@ SQL Setup
The SQL backend for the library, karma system and stats tracking requires a
MySQL server. Your server details go in /config/dbconfig.txt, and the SQL
schema is in /SQL/tgstation_schema.sql. More detailed setup instructions are
coming soon, for now ask in our IRC channel.
coming soon, for now ask in our IRC channel.
================================================================================
IRC Bot Setup
================================================================================
Included in the SVN is an IRC bot capable of relaying adminhelps to a specified IRC channel/server (thanks to Skibiliano)
Instructions for bot setup are included in the /bot/ folder along with the bot/relay script itself

13
bot/CORE_DATA.py Normal file
View File

@@ -0,0 +1,13 @@
Name = "CC_NanoTrasen" #The name he uses to connect
no_absolute_paths = True
debug_on = False
SName = ["cc","nt","trasen","nano","nanotrasen"] #Other names he will respond to
DISABLE_ALL_NON_MANDATORY_SOCKET_CONNECTIONS = False
directory = "c:/cc_nt/bot/" # Directory the bot is located in, make sure to keep the "/" at the end
version = "TG CC-BY-SA 6"
Network = 'irc.rizon.net' #e.g. "irc.rizon.net"
channel = "#italiano" #what channel you want the bot in
channels = ["#italiano"] #same as above
greeting = "Welcome!" #what he says when a person he hasn't seen before joins
prefix = "!" #prefix for bot commands
Port = 7000

32
bot/C_eightball.py Normal file
View File

@@ -0,0 +1,32 @@
from random import choice as fsample #Yay for added speed!
global responses
responses = ['Yes','Too bad','Will you turn me off if I tell you?','Absolutely',
"Not at all", "Nope", "It does", "No", "All the time",
"I don't really know", "Could be","Possibly","You're still here?",# Chaoticag
"No idea", "Of course", "Would you turn me off if I tell you?",
"Sweet!","Nah","Certainly","Yeah","Yup","I am quite confident that the answer is Yes",
"Perhaps", "Yeeeeaah... No.", "Indubitably" ] # Richard
def eightball(data,debug,sender,prefix):
global responses
arg = data.lower().replace(prefix+"eightball ","")
arg = arg.replace(prefix+"8ball ","")
if debug:
print sender+":"+prefix+"eightball", arg
if "answer" in arg and "everything" in arg and "to" in arg:
if debug:
print "Responded with",42
return "42"
elif arg == "derp":
if debug:
print "Responded with herp"
return("herp")
elif arg == "herp":
if debug:
print "Responded with derp"
return("derp")
else:
#choice = sample(responses,1)[0]
choice = fsample(responses)
if debug:
print "Responded with", choice
return(choice)

5
bot/C_heaortai.py Normal file
View File

@@ -0,0 +1,5 @@
#Throws a coin, simple.
from random import random
def heaortai(debug,sender): return("Heads" if random() > 0.5 else "Tails")
# Takes 1/6th the time of doing it with random.randint(0,1)
# This file used to be a lot bigger, now it's kind of useless.

21
bot/C_makequote.py Normal file
View File

@@ -0,0 +1,21 @@
from save_load import save
from os import listdir
import CORE_DATA
directory = CORE_DATA.directory
def mkquote(prefix,influx,sender,debug):
arg = influx[10+len(prefix):]
if debug:
print sender+":"+prefix+"makequote "+str(len(arg))+" Characters"
if len(arg) == 0:
return("Type something to a quote")
else:
files = listdir(directory+"userquotes")
numb = 0
while True:
numb += 1
if sender.lower()+str(numb) in files:
pass
else:
save(directory+"userquotes/"+sender.lower()+str(numb),[arg,sender.lower()])
return("Saved as:"+sender.lower()+str(numb))
break

70
bot/C_maths.py Normal file
View File

@@ -0,0 +1,70 @@
### EXPERIMENTAL PROTOTYPE ###
# e = 2.7182818284590452353602874713526624977572
# pi = math.pi
from __future__ import division #PYTHON Y U NO TELL ME THIS BEFORE
import math
import random
import re
e = "2.7182818284590452353602874713526624977572"
pi = str(math.pi)
global pre
pre = len("maths ")
def maths(influx,prefix="!",sender="NaN",debug=True,method="n"):
global pre
influx = influx.lower()
influx = influx[len(prefix)+pre:]
influx = influx.replace("pie",pi+"*"+e)
influx = influx.replace("e*",e+"*")
influx = influx.replace("*e","*"+e)
influx = influx.replace("pi",pi)
if debug:
print sender+":"+prefix+"maths"
if influx.count("**") == 0 and influx.count('"') == 0 and influx.count("'") == 0 and influx.count(";") == 0 and influx.count(":") == 0:
influx_low = influx.lower()
influx_hi = influx.upper()
if "0b" in influx_low:
influx_low = re.sub("0b[0-1]*","",influx_low)
influx_hi = re.sub("0B[0-1]*","",influx_hi)
if "0x" in influx_low:
influx_low = re.sub("0x[a-f0-9]*","",influx_low)
influx_hi = re.sub("0X[A-F0-9]*","",influx_hi)
if "rand" in influx_low:
influx_low = re.sub("rand","",influx_low)
influx_hi = re.sub("RAND","",influx_hi)
if influx_low == influx_hi:
influx = re.sub("rand","random.random()",influx)
try:
result = eval(influx.lower())
except ZeroDivisionError:
return "Divide by zero detected."
except SyntaxError:
return "Syntax Error detected."
except TypeError:
return "Type Error detected."
except:
return "Unknown Error detected."
else:
if method == "n": #Normal
return result
elif method == "i": #Forced Int
return int(result)
elif method == "h": #Hex
try:
if "L" in hex(result)[2:]:
return hex(result)[2:-1]
else:
return hex(result)[2:].upper()
except TypeError:
return "That value (%s) cannot be interpreted properly using !hmaths" %(str(result))
elif method == "b": #Binary
try:
return bin(result)[2:].upper()
except TypeError:
return "That value (%s) cannot be interpreted properly using !bmaths" %(str(result))
else:
return result
else:
return "What are you trying to make me do again?"
else:
return "Those are likely to make me hang"

23
bot/C_rot13.py Normal file
View File

@@ -0,0 +1,23 @@
global parta,partb
parta = {"A":"N","B":"O","C":"P","D":"Q","E":"R","F":"S","G":"T","H":"U","I":"V","J":"W","K":"X","L":"Y","M":"Z"}
partb = {'O':'B','N':'A','Q':'D','P':'C','S':'F','R':'E','U':'H','T':'G','W':'J','V':'I','Y':'L','X':'K','Z':'M'}
def rot13(text):
global parta,partb
newtext = ""
for letter in text:
try:
if letter.isupper():
newtext += parta[letter]
else:
newtext += parta[letter.upper()].lower()
except:
try:
if letter.isupper():
newtext += partb[letter]
pass
else:
newtext += partb[letter.upper()].lower()
pass
except:
newtext += letter
return newtext

96
bot/C_rtd.py Normal file
View File

@@ -0,0 +1,96 @@
import random
def rtd(data,debug,sender):
backo = data
try:
arg1,arg2 = backo.split("d")
except ValueError, err:
return("Too many or too small amount of arguments")
else:
if debug:
print sender+":!rtd "+arg1+"d"+arg2 #faster than using %s's
die,die2 = [],[]
current_mark = ""
outcome = 0
realnumberfound = False
checks = []
count = 0
arg1 = arg1.replace(" ","")
arg2 = arg2.replace(" ","")
try:
i_arg1 = int(arg1)
a_arg1 = abs(i_arg1)
if "+" in arg2 or "-" in arg2:
plus_spot = arg2.find("+")
minus_spot = arg2.find("-")
if plus_spot == -1 and minus_spot == -1:
nicer_form = ""
elif plus_spot != -1 and minus_spot == -1:
nicer_form = arg2[plus_spot:]
elif plus_spot == -1 and minus_spot != -1:
nicer_form = arg2[minus_spot:]
else:
if plus_spot < minus_spot:
nicer_form = arg2[plus_spot:]
else:
nicer_form = arg2[minus_spot:]
for letter in arg2:
if letter == "+" or letter == "-":
current_mark = letter
checks = []
count += 1
continue
checks.append(letter)
try:
next_up = arg2[count+1]
except:
if realnumberfound == False:
i_arg2 = int("".join(checks))
checks = []
realnumberfound = True
elif current_mark == "+":
outcome += int("".join(checks))
else:
outcome -= int("".join(checks))
else:
if next_up == "+" or next_up == "-":
if realnumberfound == False:
i_arg2 = int("".join(checks))
checks = []
realnumberfound = True
else:
if current_mark == "+":
outcome += int("".join(checks))
else:
outcome -= int("".join(checks))
checks = []
count += 1
else:
i_arg2 = int(arg2)
if a_arg1 == 0 or abs(i_arg2) == 0:
raise RuntimeError
except ValueError:
return("You lied! That's not a number!")
except RuntimeError:
return("Too many zeroes!")
else:
if a_arg1 > 100:
return("Too many rolls, I can only do one hundred at max.")
else:
for i in xrange(0,a_arg1):
if i_arg2 < 0:
dice = random.randint(i_arg2,0)
else:
dice = random.randint(1,i_arg2)
die.append(dice)
die2.append(str(dice))
if i_arg2 < 0:
flist = "".join(die2)
else:
flist = "+".join(die2)
if len(flist) > 350:
return(str(reduce(lambda x,y: x+y, die)+outcome))
else:
if current_mark == "":
return(flist+" = "+str(reduce(lambda x,y: x+y, die)+outcome))
else:
return(flist+" ("+nicer_form+") = "+str(reduce(lambda x,y: x+y, die)+outcome))

30
bot/C_sarcasticball.py Normal file
View File

@@ -0,0 +1,30 @@
from random import choice as fsample
sarcastic_responses = ["Yeah right","What do I look like to you?","Are you kidding me?",#UsF
"As much as you","You don't believe that yourself","When pigs fly",#UsF
"Like your grandma","You would like to know, wouldn't you?", #UsF
"Like your mom", #Spectre
"Totally","Not at all", #Spectre
"AHAHAHahahaha, No.", #Strumpetplaya
"Not as much as USER","As much as USER",
"Really, you expect me to tell you that?",
"Right, and you've been building NOUNs for those USERs in the LOCATION, haven't you?" ] #Richard
locations = ["woods","baystation","ditch"]
nouns = ["bomb","toilet","robot","cyborg",
"garbage can","gun","cake",
"missile"]
def sarcasticball(data,debug,sender,users,prefix):
arg = data.lower().replace(prefix+"sarcasticball ","")
arg = arg.replace(prefix+"sball ","")
if debug:
print sender+":"+prefix+"sarcasticball", arg
choice = fsample(sarcastic_responses)
if "USER" in choice:
choice = choice.replace("USER",fsample(users),1)
choice = choice.replace("USER",fsample(users),1)
if "NOUN" in choice:
choice = choice.replace("NOUN",fsample(nouns),1)
if "LOCATION" in choice:
choice = choice.replace("LOCATION",fsample(locations),1)
if debug:
print "Responded with", choice
return(choice)

35
bot/C_srtd.py Normal file
View File

@@ -0,0 +1,35 @@
import random
def srtd(data,debug,sender):
try:
arg1,arg2 = data.split("d")
except ValueError, err:
if str(err) == "need more than 1 value to unpack":
return("Too small amount of arguments")
else:
return("Too many arguments")
else:
if debug:
print sender+":!rtd "+arg1+"d"+arg2
die = []
arg1 = arg1.replace(" ","")
arg2 = arg2.replace(" ","")
try:
i_arg1 = int(arg1)
i_arg2 = int(arg2)
if abs(i_arg1) == 0 or abs(i_arg2) == 0:
raise RuntimeError
except ValueError:
return("You lied! That's not a number!")
except RuntimeError:
return("Too many zeroes!")
else:
if abs(i_arg1) > 500:
return("Too many rolls, I can only do five hundred at max.")
else:
for i in xrange(0,abs(i_arg1)):
if i_arg2 < 0:
dice = random.randint(i_arg2,0)
else:
dice = random.randint(1,i_arg2)
die.append(dice)
return(str(reduce(lambda x,y: x+y, die)))

60
bot/D_help.py Normal file
View File

@@ -0,0 +1,60 @@
#As new commands are added, update this.
# Last updated: 8.3.2011
# Updated 12.3.2011:
# - Added the missing help data for Version
# - Imported CORE_DATA to get the name.
# - Tidied some commands up a bit.
# - Replaced all "Bot"s with the Skibot's current name.
from CORE_DATA import Name
everything = {"8ball":"[8ball <arg>] Responds to the argument",
"allcaps":"[allcaps <arg>] Takes an uppercase string and returns a capitalized version",
"bmaths":"[bmaths <arg>] Takes a math equation (Like 5+5) and returns a binary result",
"coin":"[coin] Flips a coin",
"dance":"[dance] Makes %s do a little dance" %(Name),
"delquote":"(OP ONLY) [delquote <arg>] Removes a quote with the filename equal to the argument",
"disable":"(OP ONLY) [disable] Disables all output from %s" %(Name),
"disable dance":"(HALFOP / OP ONLY) [disable dance] or [dd] Toggles dancing",
"disable fml":"(HALFOP / OP ONLY) [disable fml] Disables FML",
"eightball":"[eightball <arg>] Responds to the argument",
"enable":"(OP ONLY) [enable] After being disabled, enable will turn output back on",
"enable fml":"{HALFOP / OP ONLY} [enable fml] After fml has been disabled, enable fml will make it available again",
"fml":"[fml] Returns a random Fuck My Life bit",
"give":"[give <arg>] Gives the Pneumatic Disposal Unit the argument",
"help":"[help [<command>]] Returns the list of commands or a detailed description of a command if specified",
"hmaths":"[hmaths <arg>] Takes a math equation (Like 5+5) and returns a hex result",
"makequote":"[makequote <arg>] Creates a quote with arg being the quote itself",
"maths":"[maths <arg>] Takes a math equation (Like 5+5) and returns a default result",
"note":"[note <arg1> [<arg2>]] Opens a note if only arg1 is specified, Creates a note with the name of arg1 and contents of arg2 if arg2 is specified, if you prefix the note name with [CP], it creates a public note only to that channel. Which can be accessed by !note _<note name>",
"notes":"[notes] Displays all your saved notes on %s" %(Name),
"otherball":"[otherball] If Floorbot is on the same channel, %s will ask him a random question when this command is passed" %(Name),
"purgemessages":"[purgemessages] Used to delete all your Tell messages (%s,Tell <User> <Message>)" %(Name),
"quote":"[quote [<author>]] Picks a random quote, if the author is specified, a random quote by that author",
"redmine":"[redmine] If you have a note called redmine, with a valid whoopshop redmine address, this displays all the bugs labeled as 'New' on that page. It also displays the todo note if it's found.",
"replace":"[replace] Fixes the Pneumatic Smasher if it's been broken",
"rot13":"[rot13 <arg>] Encrypts the arg by using the rot13 method",
"rtd":"[rtd [<arg1>d<arg2>]] Rolls a six-sided dice if no arguments are specified, otherwise arg1 is the amount of rolls and arg2 is the amount of sides the dice have",
"sarcasticball":"[sarcasticball <arg>] Responds to the argument sarcastically",
"sball":"[sball <arg>] Responds to the argument sarcastically",
"srtd":"[srtd <arg1>d<arg2>] Rolls <arg1> amount of <arg2> sided die without showing the dice values separately",
"stop":"(RESTRICTED TO OP AND CREATOR) [stop] Stops %s, plain and simple" %(Name),
"suggest":"[suggest <arg>] Saves a suggestion given to %s, to be later viewed by the creator" %(Name),
"take":"[take <arg>] Takes an item specified in the argument from the Pneumatic Smasher",
"tban":"(OP ONLY) [tban <user> <seconds>] When %s is an operator, You can ban an user for specified amount of seconds" %(Name),
"thm":"(RESTRICTED TO OP AND CREATOR) [thm] Normally in 8ball and sarcasticball, Users are not shown, instead replaced by things like demons or plasma researchers, toggling this changes that behaviour.",
"tm":"(OP AND CREATOR ONLY) [tm] Toggles marakov",
"togglequotemakers":"(OP ONLY) [togglequotemakers or tqm] Normally with the quote command, makers are not shown, this toggles that behaviour.",
"tqm":"(OP ONLY) [tqm or togglequotemakers] Normally with the quote command, makers are not shown, this toggles that behaviour.",
"toggleofflinemessages":"(OP ONLY) [toggleofflinemessages or tom] Allows an operator to toggle leaving Tell messages (%s, Tell <User> <Message)" %(Name),
"tom":"(OP ONLY) [tom or toggleofflinemessages] Allows an operator to toggle leaving Tell messages (%s, Tell <User> <Message)" %(Name),
"toggleyoutubereveal":"(OP ONLY) [toggleyoutubereveal] or [tyr] Toggles the automatic showing of youtube video titles based on URL's.",
"tyr":"(OP ONLY) [tyr] or [toggleyoutubereveal] Toggles the automatic showing of youtube video titles based on URL's.",
"translate":"(OP ONLY) [translate <user>] Whenever the user says something in allcaps, it's capitalized.",
"uptime":"[uptime] Displays how long %s has been alive on the channel."%(Name),
"use":"[use] Uses the Pneumatic Smasher.",
"youtube":"[youtube <url>] Shows the title of a video by checking the URL provided.",
"version":"[version] Shows the current version of %s." %(Name),
"weather":"[weather <location>] Displays the current weather of the provided location.",
"life":"I cannot help you with that, sorry."}

55
bot/FMLformatter.py Normal file
View File

@@ -0,0 +1,55 @@
from htmltagremove import htr
def formatter(data):
newdata = []
data = htr(data)
bad = ["Your nick : Categories : ","\r","Advanced search - last",
"FMyLife","Get the guts to spill the beans","FML: Your random funny stories",
"Woman","Man","Choose","Health","Intimacy","Miscellaneous","Man or woman? ",
"Money","Kids","Work","Love","Email notification?",
"Moderate the FMLs","Submit your FML story",
"- If your story isn't published on the website, don't feel offended, and thank you nevertheless&#33;",
"Pick a country","See all","Your account","Team's blog",
"Meet the FMLHello readers! Did you meet someone new this...The whole blog",
"Amazon","Borders","IndieBound","Personalized book","Terms of use",
"FML t-shirts -","Love - Money - Kids - Work - Health - Intimacy - Miscellaneous - Members",
"Follow the FML Follow the FML blog Follow the FML comments ",
"_qoptions={",
"};","})();","Categories","Sign up - Password? ", " Net Avenir : gestion publicitaire",
"FMyLife, the book","Available NOW on:","Barnes &amp; Noble"]
for checkable in data:
if checkable in bad:
pass
elif "_gaq.push" in checkable:
pass
elif "ga.src" in checkable:
pass
elif "var _gaq" in checkable:
pass
elif "var s =" in checkable:
pass
elif "var ga" in checkable:
pass
elif "function()" in checkable:
pass
elif "siteanalytics" in checkable:
pass
elif "qacct:" in checkable:
pass
elif "\r" in checkable:
pass
elif "ic_" in checkable:
pass
elif "Please note that spam and nonsensical stories" in checkable:
pass
elif "Refresh this page" in checkable:
pass
elif "You...The whole blo" in checkable:
pass
elif "Net Avenir : gestion publicitair" in checkable:
pass
else:
if "Net Avenir : gestion publicitaireClose the advertisement" in checkable:
checkable = checkable.replace("Net Avenir : gestion publicitaireClose the advertisement","")
newdata.append(checkable)
return newdata

2450
bot/Marakov/Marakov.Cache Normal file

File diff suppressed because it is too large Load Diff

203
bot/Marakov_Chain.py Normal file
View File

@@ -0,0 +1,203 @@
import pickle
import random
import os
import sys
import time
import CORE_DATA
def merge(d1, d2, merger=lambda x,y:x+y):
#http://stackoverflow.com/questions/38987/how-can-i-merge-two-python-dictionaries-as-a-single-expression
result = dict(d1)
for k,v in d2.iteritems():
if k in result:
result[k] = merger(result[k], v)
else:
result[k] = v
return result
full_data = {}
imported_data = {}
try:
tiedostot = os.listdir("Marakov")
except:
os.mkdir("Marakov")
tiedostot = os.listdir("Marakov")
else:
pass
listaus = []
for i in tiedostot:
if "marakov." not in i.lower():
pass
else:
listaus.append(i)
for i in listaus:
tiedosto = open("Marakov/"+i,"r")
old_size = len(full_data.keys())
if i != "Marakov.Cache":
imported_data = merge(imported_data,pickle.load(tiedosto))
print "Added contents of "+i+" (Import)"
print "Entries: "+str(len(imported_data))
else:
full_data = merge(full_data,pickle.load(tiedosto))
new_size = len(full_data.keys())
print "Added contents of "+i
print "Entries: "+str(new_size-old_size)
time.sleep(0.1)
def give_data(data):
state = False
for a,b in zip(data.split(" "),data.split(" ")[1:]):
a = a.lower().replace(",","").replace(".","").replace("?","").replace("!","").replace("(","").replace(")","").replace("[","").replace("]","").replace('"',"").replace("'","")
b = b.lower().replace(",","").replace(".","").replace("?","").replace("!","").replace("(","").replace(")","").replace("[","").replace("]","").replace('"',"").replace("'","")
if a not in [CORE_DATA.prefix+"marakov"]+CORE_DATA.SName:
state = True
if a[:7] == "http://" or a[:7] == "http:\\\\" or a[:4] == "www.":
pass
else:
try:
if b not in full_data[a]:
full_data[a].append(b)
except:
try:
if b not in imported_data[a]:
pass
except:
full_data[a] = []
full_data[a].append(b)
if state == True:
tiedosto = open("Marakov/Marakov.Cache","w")
pickle.dump(full_data,tiedosto)
tiedosto.close()
def form_sentence(argument=None):
length = 0
attempts = 0
while attempts < 20:
sentence = []
if argument != None:
a = argument
else:
try:
a = random.choice(full_data.keys())
except IndexError:
try:
b = random.choice(imported_data.keys())
except IndexError:
attempts = 999
return "No sentences formable at all"
sentence.append(a)
length = 0
attempts += 1
while length < 12 or sentence[-1].lower() in ["but","who","gets","im","most","is","it","if","then","after","over","every","of","on","or","as","the","wheather","whether","a","to","and","for"] and length < 24:
try:
b = random.choice(full_data[a])
except:
try:
b = random.choice(imported_data[a])
except IndexError:
break
except KeyError:
break
else:
sentence.append(b)
length += 1
a = b
else:
sentence.append(b)
length += 1
a = b
if len(sentence) > 5:
argument = None
return sentence
else:
pass
argument = None
return sentence
def remdata(arg):
try:
del(full_data[arg])
except:
print "There is no such data"
else:
tiedosto = open("Marakov/Marakov.Cache","w")
pickle.dump(full_data,tiedosto)
tiedosto.close()
def remobject(arg1,arg2):
try:
del(full_data[arg1][full_data[arg1].index(arg2)])
except ValueError:
print "No such object"
except KeyError:
print "No such data"
else:
tiedosto = open("Marakov/Marakov.Cache","w")
pickle.dump(full_data,tiedosto)
tiedosto.close()
def convert(filename_from,filename_to):
try:
tiedosto = open(filename_from,"r")
data = pickle.load(tiedosto)
tiedosto.close()
except:
try:
tiedosto.close()
except:
pass
print "Error!"
else:
for lista in data.keys():
try:
a = lista[-1]
except IndexError:
pass
else:
if lista[-1] in """",.?!'()[]{}""" and not lista.islower():
if lista[:-1].lower() in data.keys():
data[lista[:-1].lower()] += data[lista]
print "Added "+str(len(data[lista]))+" Objects from "+lista+" To "+lista[:-1].lower()
del(data[lista])
else:
data[lista[:-1].lower()] = data[lista]
print lista+" Is now "+lista[:-1].lower()
del(data[lista])
elif lista[-1] in """",.?!'()[]{}""" and lista.islower():
if lista[:-1] in data.keys():
data[lista[:-1]] += data[lista]
print "Added "+str(len(data[lista]))+" Objects from "+lista+" To "+lista[:-1]
del(data[lista])
else:
data[lista[:-1]] = data[lista]
print lista+" Is now "+lista[:-1]
del(data[lista])
elif not lista.islower():
if lista.lower() in data.keys():
data[lista.lower()] += data[lista]
print "Added "+str(len(data[lista]))+" Objects from "+lista+" To "+lista.lower()
del(data[lista])
else:
data[lista.lower()] = data[lista]
print lista+" Is now "+lista.lower()
del(data[lista])
for a in data.keys():
for b in data[a]:
if b.lower()[:7] == "http://" or b.lower()[:7] == "http:\\\\" or b.lower()[:4] == "www.":
data[a].pop(b)
else:
try:
if b[-1] in """",.?!'()[]{}""" and not b.islower() and not b.isdigit():
data[a].pop(data[a].index(b))
data[a].append(b[:-1].lower())
print a+" | "+b +" -> "+b[:-1].lower()
elif b[-1] in """",.?!'()[]{}""" and b.islower():
data[a].pop(data[a].index(b))
data[a].append(b[:-1].lower())
print a+" | "+b +" -> "+b[:-1]
elif not b.islower() and not b.isdigit():
data[a].pop(data[a].index(b))
data[a].append(b.lower())
print a+" | "+b +" -> "+b.lower()
except IndexError: #If it has no letters.. well.. yeah.
data[a].pop(data[a].index(b))
print "Removed a NULL object"
tiedosto = open(filename_to,"w")
pickle.dump(data,tiedosto)

19
bot/Namecheck.py Normal file
View File

@@ -0,0 +1,19 @@
def Namecheck(name,against,sender):
__doc__ = "False = No match, True = Match"
for i in against:
if i.lower() in name.lower() and sender.lower() not in name.lower():
return True
else:
pass
def Namecheck_dict(name,against):
__doc__ = "False = No match, True = Match"
fuse = False
for a,i in against.items():
if i.lower() in name.lower():
fuse = True
break
else:
pass
return fuse,a

1943
bot/NanoTrasenBot.py Normal file

File diff suppressed because it is too large Load Diff

28
bot/Shortname.py Normal file
View File

@@ -0,0 +1,28 @@
def shortname(name):
lowname = name.lower()
numb = 0
count = 0
spot = 0
for letter in name:
if letter.isupper():
spot = numb
count += 1
numb += 1
if "_" in name:
if name.count("_") > 1:
name = " ".join(name.split("_")[0:name.count("_")])
if name.lower()[-3:] == "the":
return name[:-4]
else:
return name
else:
return name.split("_")[0]
if count > 1:
if len(name[0:spot]) > 2:
return name[0:spot]
if len(name) < 5:
return name #Too short to be shortened
elif "ca" in lowname or "ct" in lowname or "tp" in lowname or "lp" in lowname:
return name[0:max(map(lambda x: lowname.find(x),["ca","ct","tp","lp"]))+1]
else:
return name[0:len(name)/2+len(name)%2]

204
bot/Timeconverter.py Normal file
View File

@@ -0,0 +1,204 @@
#Sources:
# http://wwp.greenwichmeantime.com/time-zone/usa/eastern-time/convert/
# http://www.timeanddate.com/library/abbreviations/timezones/na/
# Times are GMT +- x
# For eq.
# EST = -5
# GMT = 0
# UTC = 0
#Times are in hours,
#2.5 = 2 and half hours
global times
times = {"ADT":-3,"HAA":-3, #Synonyms on the same line
"AKDT":-8,"HAY":-8,
"AKST":-9,"HNY":-9,
"AST":-4,"HNA":-4,
"CDT":-5,"HAC":-5,
"CST":-6,"HNC":-6,
"EDT":-4,"HAE":-4,
"EGST":0,
"EGT":-1,
"EST":-5,"HNE":-5,"ET":-5,
"HADT":-9,
"HAST":-10,
"MDT":-6,"HAR":-6,
"MST":-7,"HNR":-7,
"NDT":-2.5,"HAT":-2.5,
"NST":-3.5,"HNT":-3.5,
"PDT":-7,"HAP":-7,
"PMDT":-2,
"PMST":-3,
"PST":-8,"HNP":-8,"PT":-8,
"WGST":-2,
"WGT":-3,
"GMT":0,
"UTC":0}
def converter(zones,time):
#Zones should be a list containing
# ( From zone
# To zone )
global times
#from_z = for example UTC+00:00, WGT or GMT-05:30
#to_z = same style as above.
from_z,to_z = zones
from_z = from_z.upper()
to_z = to_z.upper()
if from_z.find("+") != -1:
from_zone_offset = from_z[from_z.find("+"):]
if ":" in from_zone_offset:
try:
from_zone_offset1,from_zone_offset2 = from_zone_offset.split(":")
except ValueError:
return "Too many or too small amount of values"
try:
from_zone_offset = int(from_zone_offset1) + int(from_zone_offset2)/60.0
except:
return "Error, the 'From Zone' variable has an incorrect offset number"
else:
try:
from_zone_offset = float(from_zone_offset)
except:
return "Error, the 'From Zone' variable has an incorrect offset number"
try:
from_zone_realtime = from_zone_offset + times[from_z[:from_z.find("+")]]
except KeyError:
return "Incorrect From zone"
elif "-" in from_z:
from_zone_offset = from_z[from_z.find("-"):]
if ":" in from_zone_offset:
from_zone_offset1,from_zone_offset2 = from_zone_offset.split(":")
try:
from_zone_offset = -int(from_zone_offset1) + int(from_zone_offset2)/60.0
except:
return "Error, the 'From Zone' variable has an incorrect offset number"
else:
try:
from_zone_offset = -float(from_zone_offset)
except:
return "Error, the 'From Zone' variable has an incorrect offset number"
from_zone_realtime = times[from_z[:from_z.find("-")]] - from_zone_offset
pass
else:
from_zone_offset = 0
try:
from_zone_realtime = from_zone_offset + times[from_z]
except KeyError:
return "Incorrect From zone"
if to_z.find("+") != -1:
to_zone_offset = to_z[to_z.find("+"):]
if ":" in to_zone_offset:
try:
to_zone_offset1,to_zone_offset2 = to_zone_offset.split(":")
except ValueError:
return "Too many or too small amount of values"
try:
to_zone_offset = int(to_zone_offset1) + int(to_zone_offset2)/60.0
except:
return "Error, the 'To Zone' variable has an incorrect offset number"
else:
try:
to_zone_offset = float(to_zone_offset)
except:
return "Error, the 'To Zone' variable has an incorrect offset number"
try:
to_zone_realtime = to_zone_offset + times[to_z[:to_z.find("+")]]
except KeyError:
return "The zone you want the time to be changed to is not found"
elif "-" in to_z:
to_zone_offset = to_z[to_z.find("-"):]
if ":" in to_zone_offset:
to_zone_offset1,to_zone_offset2 = to_zone_offset.split(":")
try:
to_zone_offset = -int(to_zone_offset1) + int(to_zone_offset2)/60.0
except:
return "Error, the 'To Zone' variable has an incorrect offset number"
else:
try:
to_zone_offset = -float(to_zone_offset)
except:
return "Error, the 'To Zone' variable has an incorrect offset number"
to_zone_realtime = times[to_z[:to_z.find("-")]] -to_zone_offset
pass
else:
to_zone_offset = 0
try:
to_zone_realtime = to_zone_offset + times[to_z]
except KeyError:
return "Incorrect To zone"
try:
time_hour,time_minute = time.split(":")
time_hour,time_minute = int(time_hour),int(time_minute)
string = ":"
except:
try:
time_hour,time_minute = time.split(".")
time_hour,time_minute = int(time_hour),int(time_minute)
string = "."
except ValueError:
return "The time was input in an odd way"
if to_zone_realtime % 1.0 == 0.0 and from_zone_realtime % 1.0 == 0.0:
time_hour = time_hour + (to_zone_realtime - from_zone_realtime)
return str(int(time_hour))+string+str(int(time_minute))
else:
if to_zone_realtime % 1.0 != 0.0 and from_zone_realtime % 1.0 != 0.0:
time_minute = time_minute + (((to_zone_realtime % 1.0) * 60) - ((from_zone_realtime % 1.0) * 60))
elif to_zone_realtime % 1.0 != 0.0 and from_zone_realtime % 1.0 == 0.0:
time_minute = time_minute + (((to_zone_realtime % 1.0) * 60) - 0)
elif to_zone_realtime % 1.0 == 0.0 and from_zone_realtime % 1.0 != 0.0:
time_minute = time_minute + (0 - ((from_zone_realtime % 1.0) * 60))
else:
print "Wut?"
time_hour = time_hour + (int(to_zone_realtime//1) - int(from_zone_realtime//1))
return str(int(time_hour))+string+str(int(time_minute))
def formatter(time):
if "." in time:
string = "."
elif ":" in time:
string = ":"
else:
return time
hours,minutes = time.split(string)
days = 0
if int(minutes) < 0:
buphours = int(hours)
hours,minutes = divmod(int(minutes),60)
hours += buphours
if int(minutes) > 60:
hours,minutes = divmod(int(minutes),60)
hours += int(hours)
if int(hours) < 0:
days = 0
days,hours = divmod(int(hours),24)
if int(hours) > 24:
days = 0
days,hours = divmod(int(hours),24)
if int(hours) == 24 and int(minutes) > 0:
days += 1
hours = int(hours) - 24
hours = str(hours)
minutes = str(minutes)
if len(minutes) == 1:
minutes = "0"+minutes
if len(hours) == 1:
hours = "0"+hours
if days > 0:
if days == 1:
return hours+string+minutes+" (Tomorrow)"
else:
return hours+string+minutes+" (After "+str(days)+" days)"
elif days < 0:
if days == -1:
return hours+string+minutes+" (Yesterday)"
else:
return hours+string+minutes+" ("+str(abs(days))+" days ago)"
return hours+string+minutes

61
bot/Weather.py Normal file
View File

@@ -0,0 +1,61 @@
# -*- coding: cp1252 -*-
import urllib,xml.sax.handler
# S10 COMPATIABLE
def message(data):
if data["type"] == "PRIVMSG":
try:
splitdata = data["content"].lower().split(" ")
if splitdata[0] == ":weather" and len(splitdata) > 1:
data = Weather(" ".join(splitdata[1:]))
data["conn"].privmsg(data["target"],"Weather for "+data[1]+": "+data[0])
return True
except KeyError:
print "WUT"
else:
return -1
def Weather(question):
question = question.replace("<EFBFBD>","a")
url = "http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml?query="+question
opener = urllib.FancyURLopener({})
f = opener.open(url)
data = f.read()
f.close()
bufferi = []
seen = False
for i in data.split("\n"):
if "<temperature_string>" in i:
stuff = cutter(i,"<temperature_string>")
if len(stuff) > 7:
bufferi.append("Temperature: "+stuff)
elif "<observation_time>" in i:
stuff = cutter(i,"<observation_time>")
if len(stuff) > 19:
bufferi.append(stuff)
elif "<weather>" in i:
stuff = cutter(i,"<weather>")
if len(stuff) > 0:
bufferi.append("Weather: "+stuff)
elif "<relative_humidity>" in i:
stuff = cutter(i,"<relative_humidity>")
if len(stuff) > 0:
bufferi.append("Humidity: "+stuff)
elif "<wind_string>" in i:
stuff = cutter(i,"<wind_string>")
if len(stuff) > 0:
bufferi.append("Wind blows "+stuff)
elif "<pressure_string>" in i:
stuff = cutter(i,"<pressure_string>")
if len(stuff) > 9:
bufferi.append("Air pressure is "+stuff)
elif "<full>" in i and seen == False:
seen = True
where = cutter(i,"<full>")
if len(where) == 4:
where = "Location doesn't exist"
return [", ".join(bufferi),where]
def cutter(fullstring,cut):
fullstring = fullstring.replace(cut,"")
fullstring = fullstring.replace("</"+cut[1:],"")
fullstring = fullstring.replace("\t","")
return fullstring

75
bot/YTCv3.py Normal file
View File

@@ -0,0 +1,75 @@
from urllib2 import urlopen
from CORE_DATA import directory,no_absolute_paths
def YTCV2(youtube_url,cache=1,debug=0):
import time
__doc__ = "Cache 0 = No cache access, Cache 1 = Cache access (Default)"
if cache == 1:
import md5
import pickle
crypt = md5.md5(youtube_url)
try:
cryp = crypt.hexdigest()
if no_absolute_paths:
tiedosto = open("YTCache/"+cryp,"r")
else:
tiedosto = open(directory+"\NanoTrasen\YTCache\\"+cryp,"r")
aha = pickle.load(tiedosto)
tiedosto.close()
return aha[0]
except:
if no_absolute_paths:
tiedosto = open("YTCache/"+crypt.hexdigest(),"w")
else:
tiedosto = open(directory+"\NanoTrasen\YTCache\\"+crypt.hexdigest(),"w")
else:
pass
youtube_url = youtube_url.replace("http//","http://")
if youtube_url.lower()[0:7] != "http://" and youtube_url[0:4] == "www.":
youtube_url = "http://" + youtube_url
if youtube_url.count("/") + youtube_url.count("\\") < 3:
return "Reflex: Video cannot exist"
else:
if youtube_url[0:7].lower() != "http://":
return "Reflex: Incorrect link start"
try:
website = urlopen(youtube_url)
except:
return "Reflex: Incorrect link!"
for i in website:
if i.count('<meta name="title" content') == 1:
epoch = time.time()
if type(i[30:-3]) != str:
if cache == 1:
aha = ["No title for video",epoch]
pickle.dump(aha,tiedosto)
tiedosto.close()
tiedosto.close()
return "Video deleted"
else:
result = i[30:-3]
if "&amp;quot;" in result:
result = result.replace("&amp;quot;",'"')
else:
pass
if "&amp;amp;" in result:
result = result.replace("&amp;amp;","&")
else:
pass
if "&amp;#39;" in result:
result = result.replace("&amp;#39;","'")
else:
pass
if cache == 1:
aha = [result,epoch]
pickle.dump(aha,tiedosto)
tiedosto.close()
tiedosto.close()
return result
if cache == 1:
epoch = time.time()
aha = ["No title for video, could be removed / does not exist at all",epoch]
pickle.dump(aha,tiedosto)
tiedosto.close()
tiedosto.close()
return "No title for video, could be removed / does not exist at all"

132
bot/YTCv4.py Normal file
View File

@@ -0,0 +1,132 @@
from urllib2 import urlopen
import os
import pickle
from CORE_DATA import directory,no_absolute_paths
global did_tell, no_absolute_paths
no_absolute_paths = True
did_tell = False
def YTCV4(youtube_url,cache=1,debug=0):
global did_tell, no_absolute_paths
Do_not_open = True
__doc__ = "Cache does not affect anything, it's legacy for skibot."
try:
cut_down = youtube_url.split("watch?v=")[1].split("&")[0]
if len(cut_down) > 11: #Longer than normal, presume troll.
youtube_url.replace(cut_down,cut_down[:11])
elif len(cut_down) < 11: #Shorter than normal
pass
except IndexError:
return "Reflex: Where's the watch?v=?"
first_two = cut_down[0:2]
try:
if no_absolute_paths:
tiedosto = open("YTCache/"+first_two+".tcc","r")
else:
tiedosto = open(directory+"YTCache/"+first_two+".tcc","r")
except:
prev_dict = {}
else:
try:
prev_dict = pickle.load(tiedosto)
except EOFError: # Cache is corrupt
os.remove(directory+"/nano/"+tiedosto.name)
print "REMOVED CORRUPT CACHE: "+tiedosto.name
prev_dict = {}
tiedosto.close() # I think this should belong here.
if cut_down in prev_dict.keys():
return prev_dict[cut_down]
else:
pass
try:
if no_absolute_paths:
tiedosto = open("YTCache/"+first_two+".tcc","w")
else:
tiedosto = open(directory+"YTCache/"+first_two+".tcc","w")
except IOError,error:
if len(prev_dict.keys()) > 0:
try:
tiedosto = open(directory+"YTCache/"+first_two+".tcc","w") #This is a Just In Case
except IOError:
if did_tell == False:
did_tell = True
return "COULD NOT ACCESS FILE "+first_two+".tcc! The next time you run this link, it checks it through the web"
Do_not_open = False
else:
did_tell = False
pickle.dump(prev_dict,tiedosto)
tiedosto.close()
else:
pass
return "Very odd error occurred: " + str(error)
youtube_url = youtube_url.replace("http//","http://")
if youtube_url.lower()[0:7] != "http://" and youtube_url[0:4] == "www.":
youtube_url = "http://" + youtube_url
if youtube_url.count("/") + youtube_url.count("\\") < 3:
if len(prev_dict.keys()) > 0:
if Do_not_open == True:
tiedosto = open(directory+"YTCache/"+first_two+".tcc","w") #This is a Just In Case
pickle.dump(prev_dict,tiedosto)
tiedosto.close()
else:
pass
return "Reflex: Video cannot exist"
else:
if "http://" in youtube_url[0:12].lower() and youtube_url[0:7].lower() != "http://":
youtube_url = youtube_url[youtube_url.find("http://"):]
elif youtube_url[0:7].lower() != "http://":
if len(prev_dict.keys()) > 0:
if Do_not_open == True:
tiedosto = open(directory+"YTCache/"+first_two+".tcc","w") #This is a Just In Case
pickle.dump(prev_dict,tiedosto)
tiedosto.close()
return "Reflex: Incorrect link start"
if "?feature=player_embedded&" in youtube_url:
youtube_url = youtube_url.replace("?feature=player_embedded&","?")
try:
website = urlopen(youtube_url)
except:
if len(prev_dict.keys()) > 0:
if Do_not_open == True:
tiedosto = open(directory+"YTCache/"+first_two+".tcc","w") #This is a Just In Case
pickle.dump(prev_dict,tiedosto)
tiedosto.close()
else:
pass
return "Reflex: Incorrect link!"
for i in website.readlines():
if i.count('<meta name="title" content') == 1:
if type(i[30:-3]) != str:
if Do_not_open == True:
tiedosto = open(directory+"YTCache/"+first_two+".tcc","w") #This is a Just In Case
prev_dict[cut_down] = "No title for video"
pickle.dump(prev_dict,tiedosto)
tiedosto.close()
return "Video deleted"
else:
#result = i[30:-3]
contentvar = i.find('content="')
result = i[contentvar+5:i.find('">',contentvar)]
if "&amp;quot;" in result:
result = result.replace("&amp;quot;",'"')
else:
pass
if "&amp;amp;" in result:
result = result.replace("&amp;amp;","&")
else:
pass
if "&amp;#39;" in result:
result = result.replace("&amp;#39;","'")
else:
pass
if Do_not_open == True:
tiedosto = open(directory+"YTCache/"+first_two+".tcc","w") #This is a Just In Case
prev_dict[cut_down] = result
pickle.dump(prev_dict,tiedosto)
tiedosto.close()
return result
if Do_not_open == True:
tiedosto = open(directory+"YTCache/"+first_two+".tcc","w") #This is a Just In Case
prev_dict[cut_down] = "No title for video, Removed / Needs Age verification / Does not exist"
pickle.dump(prev_dict,tiedosto)
tiedosto.close()
return "No title for video, Removed / Needs age verification / Does not exist"

74
bot/_____Readme.txt Normal file
View File

@@ -0,0 +1,74 @@
/// Adminhelp relay IRC bot setup guide
/// CC_Nanotrasen bot created by Skibiliano and distributed under the CC-BY-SA 3.0 license
/// All derivative works of this bot must properly credit Skibiliano as the original author
/// Big thanks to Skibiliano his bot and allowing distribution, and to BS12 for sharing their code for making use of it ingame
QUESTION: What does this bot do?
ANSWER: It, in conjunction with BYOND, relays adminhelps to a designated channel, along with various extra functions that can be accessed by saying !help in the same channel/in a query with the bot.
Some basic info before you set this up:
CC_Nanotrasen is coded in python 2.6 and requires a serverside installation of python 2.6 (obtainable at http://www.python.org/getit/releases/2.6/)
- Python MUST BE installed to the same directory as the .dmb you are using to host your server/server config folder
- CC_Nanotrasen supports, but does not require, Psyco (obtainable at http://psyco.sourceforge.net/download.html) which increases the speed 20-30% and slightly increases RAM usage
Now that that's out of the way, I'll teach you how to set this up.
BOT CONFIG:
Move everything in this folder (this file noninclusive) to the same folder as the hosting server (where your .dmb, config folder, and python are installed)
Open CORE_DATA.py with a text editor of your choice (recommended to be notepad++ or notepad)
You should see 14 lines of code which look like
Name = "CC_NanoTrasen" #The name he uses to connect
no_absolute_paths = True #Do not change this.
debug_on = False
SName = ["cc","nt","trasen","nano","nanotrasen"] #Other names he will respond to, must be lowercase
DISABLE_ALL_NON_MANDATORY_SOCKET_CONNECTIONS = False
directory = "BOT DIRECTORY GOES HERE/" #make sure to keep the "/" at the end
version = "TG CC-BY-SA 6"
Network = 'irc.server.goes.here' #e.g. "irc.rizon.net"
channel = "#CHANNEL GOES HERE" #what channel you want the bot in
channels = ["#CHANNEL GOES HERE","#ALSO ANOTHER CHANNEL GOES HERE IF YOU WANT"] #same as above
greeting = "Welcome!" #what he says when a person he hasn't seen before joins
prefix = "!" #prefix for bot commands
Port = 7000
There are some basic comments besides every important config option in here, but I'll summarize them in detail
NAME - The name the bot assumes when it connects to IRC, so in this example it would join the IRC under the nickname "CC_Nanotrasen"
SNAME - A list of secondary names, with commas, that the bot will respond to for commands (for example, this setup will allow the bot to respond to "nt, tell quarxink he's a terrible writer")
DIRECTORY - The directory of the bot files, dmb, python, and config folder IN FORWARD SLASHES, WITH FORWARD SLASH AT THE END(for example, I host my test server from "c:\tgstation\tgstation13\tgstation.dmb" so for me the line would say directory = "c:/tgstation/tgstation13/")
NETWORK - The IRC server it will connect to, such as "irc.rizon.net"
CHANNEL/CHANNELS - what channel the bot will join (channels allows for multiple channel connections, in the same formatting as SName separates nicknames)
GREETING - CC_Nanotrasen will store the names of people it has seen before, but when a nickname joins that it hasn't seen before it will greet that person with whatever message is put in this
PREFIX = What character/string will be placed before commands for the bot (so if you changed this to "$", you would pull up the bot's help menu by saying $help instead of !help)
PORT - What port to connect to for the IRC server (if you are unsure of what port to use, most IRC clients will show you what port you are connecting to)
Once you have that ready, you're on to step two.
Open up the config folder in your install dir, and open config.txt
Scroll to the bottom, right below #FORBID_SINGULO_POSSESSION should be
##Remove the # mark if you are going to use the SVN irc bot to relay adminhelps
#USEIRCBOT
Just remove the "#" in front of USEIRCBOT (you don't even have to recompile your DMB!
Got that all ready to go? Good, it's time for step three.
Open Dream Daemon (that thing you use when you host)
On the bottom of the window you should see port, security, and visibility.
Change security to "Trusted"
Congratulations, you've set up this bot!
A few things to note as far as features:
Use !help to list most commands for the bot.
You can leave notes for other users! Just say "[bot name], tell [other user's name] [message]"
So let's say you wonder if I'm going to jump in to your IRC ever and you want to tell me this readme was horrible, you would say "Nano, tell Quarxink Your readme was horrible"
TROUBLESHOOTING:
Attempting to run the bot gives me an error about encoding.utf-8.
You've probably installed python to a separate folder than the bot/server, move python's files over and it should run fine
It's telling me connection refused when someone adminhelps.
You've moved the bot to a separate folder from the nudge script, most likely.
BYOND asks me on any restart if I want to allow nudge.py to run.
Set security to trusted in Dream Daemon
If you have any requests, suggestions, or issues not covered by this guide, I can be contacted as Quarxink at #coderbus on irc.rizon.net (If I don't respond, leave me a query with your problem and how to reach you [preferably an email address, steam, other irc channel, or aim/msn])

15
bot/gen_fml.py Normal file
View File

@@ -0,0 +1,15 @@
from FMLformatter import formatter
from urllib2 import urlopen
try:
from hashlib import md5
except:
from md5 import md5
from save_load import save,load
import CORE_DATA
directory = CORE_DATA.directory
FML = urlopen("http://www.fmylife.com/random")
formatted = formatter(FML.read().split("\n"))
for Quote in formatted:
exact = Quote[:Quote.find("#")]
# print exact
save(directory+"fmlquotes/"+md5(exact).hexdigest()+".txt",exact)

28
bot/htmltagremove.py Normal file
View File

@@ -0,0 +1,28 @@
def htr(data):
ignore = False
if type(data) == list:
b = []
for olio in data:
tempolio = ""
for letter in olio:
if letter == "<":
ignore = True
else:
pass
if ignore != True:
tempolio += letter
else:
pass
if letter == ">":
ignore = False
else:
pass
tempolio = tempolio.replace("\t","")
if len(tempolio) == 0:
pass
elif len(tempolio.replace(" ","")) == 0:
pass
else:
b.append(tempolio)
#Finetuning
return b

94
bot/irchat.py Normal file
View File

@@ -0,0 +1,94 @@
import socket
import time
class IRC:
queue = []
partial = ''
def __init__ ( self, network, port, name, hostName, serverName, realName ):
self.network = network
self.port = port
self.hostName = hostName
self.serverName = serverName
self.realName = realName
self.socket = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
self.socket.connect ( ( self.network, self.port ) )
self.address = self.socket.getpeername()
self.nick ( name )
self.send ( 'USER ' + self.name + ' ' + self.serverName + ' ' + self.hostName + ' :' + self.realName )
def quit ( self ):
self.send ( 'QUIT' )
self.socket.close()
def send ( self, text ):
count = 0
try:
count += 1
self.socket.send ( text + '\r\n' )
except:
if count > 10:
time.sleep(1)
self.socket.send(text+'\r\n')
else:
count = 0
def nick ( self, name ):
self.name = name
self.send ( 'NICK ' + self.name )
def addressquery(self):
print self.address
aha = socket.gethostbyaddr(str(self.address[0]))
return aha
def recv ( self, size = 2048 ):
commands = self.socket.recv ( size ).split ( '\r\n' )
if len ( self.partial ):
commands [ 0 ] = self.partial + commands [ 0 ]
self.partial = ''
if len ( commands [ -1 ] ):
self.partial = commands [ -1 ]
self.queue.extend ( commands [ :-1 ] )
else:
self.queue.extend ( commands )
def retrieve ( self ):
if len ( self.queue ):
command = self.queue [ 0 ]
self.queue.pop ( 0 )
return command
else:
return False
def dismantle ( self, command ):
if command:
source = command.split ( ':' ) [ 1 ].split ( ' ' ) [ 0 ]
parameters = command.split ( ':' ) [ 1 ].split ( ' ' ) [ 1: ]
if len(parameters) > 0:
if not len ( parameters [ -1 ] ):
parameters.pop()
if command.count ( ':' ) > 1:
parameters.append(command[command.find(":",command.find(":")+1)+1:])
return source, parameters
def privmsg ( self, destination, message ):
self.send ( 'PRIVMSG ' + destination + ' :' + message )
def handshake(self,hexstring):
self.send("PONG :"+hexstring)
def notice ( self, destination, message ):
self.send ( 'NOTICE ' + destination + ' :' + message )
def join ( self, channel ):
self.send ( 'JOIN ' + channel )
def part ( self, channel ):
self.send ( 'PART ' + channel )
def topic ( self, channel, topic = '' ):
self.send ( 'TOPIC ' + channel + ' ' + topic )
def names ( self, channel ):
self.send ( 'NAMES ' + channel )
def invite ( self, nick, channel ):
self.send ( 'INVITE ' + nick + ' ' + channel )
def mode ( self, channel, mode, nick = '' ):
self.send ( 'MODE ' + channel + ' ' + mode + ' ' + nick )
def banon(self,channel,name):
self.mode(channel,"+b",name)
def banoff(self,channel,name):
self.mode(channel,"-b",name)
def kick ( self, channel, nick, reason = '' ):
self.send ( 'KICK ' + channel + ' ' + nick + ' ' + reason )
def who ( self, pattern ):
self.send ( 'WHO ' + pattern )
def whois ( self, nick ):
self.send ( 'WHOIS ' + nick )
def whowas ( self, nick ):
self.send ( 'WHOWAS ' + nick )

43
bot/linereader.py Normal file
View File

@@ -0,0 +1,43 @@
import os
directory = ""
raw = os.listdir(directory)
extract = []
for i in raw:
if i[-3:] == ".py":
extract.append(i)
toc = 0
toc3 = 0
toc2 = 0
print len(extract),"Files"
lista = []
for ob in extract:
count3 = 0
if directory == "":
tiedosto = open(ob,"r")
tiedosto2 = open(ob,"r")
count3 += os.path.getsize(ob)
toc3 += count3
else:
tiedosto = open(directory+"/"+ob,"r")
tiedosto2 = open(directory+"/"+ob,"r")
count3 += os.path.getsize(directory+"/"+ob)
toc3 += count3
count = 0
count2 = 0
line = tiedosto.readline()
while line != "":
count += 1
toc += 1
line = tiedosto.readline()
count2 += len(tiedosto2.read())
toc2 += count2
lista.append([count,count2,ob,count3])
tiedosto.close()
tiedosto2.close()
print toc,"Lines in total"
print toc2,"Letters in total"
print toc3,"Bytes in total"
for linecount, lettercount, filename, bytecount in lista:
print str(linecount)+" Lines (%s%%) || "%(str(round((float(linecount)/toc)*100,1))),str(lettercount)+" Letters (%s%%) in file " %(str(round((float(lettercount)/toc2)*100,1)))+filename
print str(bytecount) + " Bytes (%s%%) "%(str(round((float(bytecount)/toc3)*100,1)))

39
bot/nudge.py Normal file
View File

@@ -0,0 +1,39 @@
import sys,pickle,socket, CORE_DATA
#def pack():
# path = "/home/ski/Nanotrasen/message.txt"
# ip = sys.argv[1]
# dictionary = {"ip":ip,"data":1}
# try:
# targetfile = open(path,"r")
# except IOError:
# targetfile = open(path,"w")
# pickle.dump(dictionary,targetfile)
# targetfile.close()
# nudge()
# else:
# targetfile.close() #Professionals, have standards.
# pass
def pack():
ip = sys.argv[1]
try:
data = sys.argv[2:] #The rest of the arguments is data
except:
data = "NO DATA SPECIFIED"
dictionary = {"ip":ip,"data":data}
pickled = pickle.dumps(dictionary)
nudge(pickled)
def nudge(data):
if CORE_DATA.DISABLE_ALL_NON_MANDATORY_SOCKET_CONNECTIONS:
pass
else:
HOST = "localhost"
PORT = 45678
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
s.send(data)
s.close()
if __name__ == "__main__" and len(sys.argv) > 1: # If not imported and more than one argument
pack()

24
bot/save_load.py Normal file
View File

@@ -0,0 +1,24 @@
import pickle
def save(filename,data,dnrw=0):
if dnrw == 1:
try:
tiedosto = open(filename,"r")
except:
tiedosto = open(filename,"w")
else:
return False
else:
tiedosto = open(filename,"w")
if "http//" in data:
data = data.replace("http//","http://")
pickle.dump(data,tiedosto)
tiedosto.close()
def load(filename):
try:
tiedosto = open(filename,"r")
except IOError:
return "ERROR ERROR ERROR ERR"
a = pickle.load(tiedosto)
tiedosto.close()
return a

20
bot/some_but_not_all_2.py Normal file
View File

@@ -0,0 +1,20 @@
def sbna2(only_one,one_of_these,data):
if type(only_one) != list:
only_one = list(only_one)
if type(data) != list:
data = data.split(" ")
count = 0
for datoid in only_one:
if datoid in data and count >= 1:
return False
elif datoid in data:
count += 1
pass
else:
pass
if count == 0:
return False
for datoid in one_of_these:
if datoid in data:
return True
return False

40
bot/xkcdparser.py Normal file
View File

@@ -0,0 +1,40 @@
from urllib2 import urlopen
from json import loads
from pickle import dump,load
from CORE_DATA import no_absolute_paths
def xkcd(link):
try:
filename = link[link.find("xkcd.com")+9:].replace("/","").replace("\\","")
if no_absolute_paths:
tiedosto = open("xkcdcache/"+filename,"r")
else:
tiedosto = open(directory+"xkcdcache/"+filename,"r")
except:
try:
if no_absolute_paths:
tiedosto = open("xkcdcache/"+filename,"w")
else:
tiedosto = open(directory+"xkcdcache/"+filename,"w")
except IOError:
return "NOTHING"
else:
try:
return load(tiedosto)
except EOFError:
tiedosto = open("xkcdcache/"+filename,"w")
pass #Corrupt cache, moving on.
if link[-1] == "/" or link[-1] == "\\": #Ending is fine.
link += "info.0.json"
else:
link += "/info.0.json"
try:
data = urlopen(link).read()
except:
return "NOTHING"
try:
newdata = loads(data)["title"]
dump(newdata,tiedosto)
return newdata
except:
return "NOTHING"

View File

@@ -51,6 +51,7 @@
var/alert_desc_delta = "The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill."
var/forbid_singulo_possession = 0
var/useircbot = 0
//game_options.txt configs
@@ -251,6 +252,9 @@
if("forbid_singulo_possession")
forbid_singulo_possession = 1
if("useircbot")
useircbot = 1
else
diary << "Unknown setting in configuration: '[name]'"

View File

@@ -23,4 +23,10 @@
log_admin("HELP: [key_name(src)]: [msg]")
if(tension_master)
tension_master.new_adminhelp()
send2irc(usr.ckey, msg)
return
proc/send2irc(msg,msg2)
if(config.useircbot)
shell("python nudge.py [msg] [msg2]")
return

View File

@@ -110,4 +110,7 @@ HOSTEDBY Yournamehere
# LOAD_JOBS_FROM_TXT
##Remove the # mark infront of this to forbid admins from posssessing the singularity.
#FORBID_SINGULO_POSSESSION
#FORBID_SINGULO_POSSESSION
##Remove the # mark if you are going to use the SVN irc bot to relay adminhelps
#USEIRCBOT