mirror of
https://git.wownero.com/wownero/tippero.git
synced 2024-08-15 00:33:14 +00:00
commit
c69bef1a41
9 changed files with 260 additions and 37 deletions
|
@ -15,7 +15,7 @@ coinspecs = {
|
|||
"symbol": "XMR",
|
||||
"atomic_units": 1e12,
|
||||
"denominations": [[1000000, 1, "piconero"], [1000000000, 1e6, "micronero"], [1000000000000, 1e9, "millinero"]],
|
||||
"address_length": [95, 95], # min/max size of addresses
|
||||
"address_length": [[95, 95], [106, 106]], # min/max size of addresses
|
||||
"address_prefix": ['4', '9'], # allowed prefixes of addresses
|
||||
"min_withdrawal_fee": 10000000000,
|
||||
"web_wallet_url": "https://mymonero.com/", # None is there's none
|
||||
|
|
|
@ -28,6 +28,7 @@ payment_confirmations = 6
|
|||
tipbot_balance_cache_time = 35 # seconds
|
||||
site_game_salt = ''
|
||||
openalias_address = None
|
||||
rpc_timeout = 180
|
||||
|
||||
admins = ["freenode:moneromooo", "freenode:moneromoo"]
|
||||
|
||||
|
@ -116,3 +117,4 @@ kitsune_max_loss = 35
|
|||
# how much are we prepared to lose as a ratio of our current pot
|
||||
kitsune_max_loss_ratio = 0.1
|
||||
|
||||
spammer_allowed = ['_Slack', 'i2p-relay']
|
||||
|
|
|
@ -29,7 +29,8 @@ def Announce(link,cmd):
|
|||
return
|
||||
nextid=redis_get('cryptokingdom:announcements:nextid')
|
||||
if nextid==None:
|
||||
nextid=0
|
||||
nextid=1
|
||||
nextid=long(nextid)
|
||||
text = " ".join(cmd[1:])
|
||||
redis_hset('cryptokingdom:announcements',nextid,'From %s: %s'%(link.user.nick,text))
|
||||
nextid+=1
|
||||
|
@ -54,8 +55,8 @@ def Cancel(link,cmd):
|
|||
redis_hdel('cryptokingdom:announcements',which)
|
||||
|
||||
def Help(link):
|
||||
link.send(link,'Announce anything that you want others to know')
|
||||
link.send(link,'Offers, auctions, other information')
|
||||
link.send_private('Announce anything that you want others to know')
|
||||
link.send_private('Offers, auctions, other information')
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -314,6 +314,8 @@ class IRCNetwork(Network):
|
|||
self.update_last_active_time(chan,GetNick(who))
|
||||
# resplit to avoid splitting text that contains ':'
|
||||
text = data.split(' :',1)[1]
|
||||
if self.on_event:
|
||||
self.on_event('message',link=Link(self,User(self,GetNick(who),who),Group(self,chan)),message=text)
|
||||
exidx = text.find('!')
|
||||
if exidx != -1 and len(text)>exidx+1 and text[exidx+1] in string.ascii_letters and self.is_acceptable_command_prefix(text[:exidx]):
|
||||
cmd = text.split('!')[1]
|
||||
|
@ -338,7 +340,7 @@ class IRCNetwork(Network):
|
|||
self.userstable[chan][nick] = None
|
||||
log_log("New list of users in %s: %s" % (chan, str(self.userstable[chan].keys())))
|
||||
if self.on_event:
|
||||
self.on_event('user-joined',link=Link(self,User(self,nick),Group(self,chan)))
|
||||
self.on_event('user-joined',link=Link(self,User(self,nick,who),Group(self,chan)))
|
||||
|
||||
elif action == 'PART':
|
||||
nick = GetNick(who)
|
||||
|
@ -443,6 +445,8 @@ class IRCNetwork(Network):
|
|||
(r,w,x)=select.select([self.irc.fileno()],[],[],1)
|
||||
if self.irc.fileno() in r:
|
||||
newdata=self._irc_recv(4096,socket.MSG_DONTWAIT)
|
||||
if len(newdata) == 0:
|
||||
raise RuntimeError('0 bytes received, EOF')
|
||||
else:
|
||||
newdata = None
|
||||
if self.irc.fileno() in x:
|
||||
|
|
|
@ -161,14 +161,18 @@ def UpdateCoin(data):
|
|||
def Deposit(link,cmd):
|
||||
Help(link)
|
||||
|
||||
def RandomPaymentID(link,cmd):
|
||||
link.send_private(" New payment ID: %s" % GetRandomPaymentID(link))
|
||||
|
||||
def Help(link):
|
||||
GetAccount(link.identity())
|
||||
link.send_private("You can send %s to your account:" % coinspecs.name);
|
||||
link.send_private("You can send %s to your account using this address AND payment ID:" % coinspecs.name);
|
||||
address=GetTipbotAddress() or 'ERROR'
|
||||
link.send_private(" Address: %s" % address)
|
||||
if config.openalias_address != None:
|
||||
link.send_private(" (or %s when using OpenAlias)" % config.openalias_address)
|
||||
link.send_private(" Payment ID: %s" % GetPaymentID(link))
|
||||
link.send_private(" Use your primary payment ID: %s" % GetPaymentID(link))
|
||||
link.send_private(" OR generate random payment ids at will with: !randompid")
|
||||
link.send_private("Incoming transactions are credited after %d confirmations" % config.payment_confirmations)
|
||||
|
||||
RegisterModule({
|
||||
|
@ -182,4 +186,11 @@ RegisterCommand({
|
|||
'function': Deposit,
|
||||
'help': "Show instructions about depositing %s" % coinspecs.name
|
||||
})
|
||||
RegisterCommand({
|
||||
'module': __name__,
|
||||
'name': 'randompid',
|
||||
'function': RandomPaymentID,
|
||||
'registered': True,
|
||||
'help': "Generate a new random payment ID"
|
||||
})
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import time
|
|||
import threading
|
||||
import re
|
||||
import praw
|
||||
import logging
|
||||
import tipbot.config as config
|
||||
from tipbot.log import log_error, log_warn, log_info, log_log
|
||||
from tipbot.user import User
|
||||
|
@ -44,7 +45,7 @@ class RedditNetwork(Network):
|
|||
try:
|
||||
cfg=config.network_config[self.name]
|
||||
self.login=cfg['login']
|
||||
password=GetPassword(self.name)
|
||||
password=GetPassword(self.name+'/password')
|
||||
self.subreddits=cfg['subreddits']
|
||||
user_agent=cfg['user_agent']
|
||||
self.update_period=cfg['update_period']
|
||||
|
@ -52,9 +53,19 @@ class RedditNetwork(Network):
|
|||
self.keyword=cfg['keyword']
|
||||
self.use_unread_api=cfg['use_unread_api']
|
||||
self.cache_timeout=cfg['cache_timeout']
|
||||
client_id=GetPassword(self.name+'/client_id')
|
||||
client_secret=GetPassword(self.name+'/client_secret')
|
||||
username=GetPassword(self.name+'/username')
|
||||
|
||||
self.reddit=praw.Reddit(user_agent=user_agent,cache_timeout=self.cache_timeout)
|
||||
self.reddit.login(self.login,password)
|
||||
if False:
|
||||
handler = logging.StreamHandler()
|
||||
handler.setLevel(logging.DEBUG)
|
||||
logger = logging.getLogger('prawcore')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.addHandler(handler)
|
||||
|
||||
self.reddit=praw.Reddit(client_id=client_id,client_secret=client_secret,password=password,user_agent=user_agent,username=username)
|
||||
log_info("Logged in reddit as " + str(self.reddit.user.me()))
|
||||
self.items_cache=dict()
|
||||
|
||||
self.stop = False
|
||||
|
@ -107,18 +118,23 @@ class RedditNetwork(Network):
|
|||
return
|
||||
if not hasattr(item.author,'name'):
|
||||
log_warn('author of %s has no name field, ignored' % str(item.id))
|
||||
try:
|
||||
item.mark_as_read()
|
||||
except Exception,e:
|
||||
log_warning('Failed to mark %s as read: %s' % (item.id,str(e)))
|
||||
if True:
|
||||
try:
|
||||
item.mark_read()
|
||||
except Exception,e:
|
||||
log_warn('Failed to mark %s as read: %s' % (item.id,str(e)))
|
||||
return
|
||||
|
||||
author=self.canonicalize(item.author.name)
|
||||
if author==self.canonicalize(self.login):
|
||||
if author and author==self.canonicalize(self.login):
|
||||
return
|
||||
|
||||
if item.id in self.last_seen_ids:
|
||||
#log_log('Already seen %s %.1f hours ago by %s: %s (%s), skipping' % (item.id,age/3600,str(author),repr(title),repr(item.body)))
|
||||
log_log('Already seen %s %.1f hours ago by %s: %s (%s), skipping' % (item.id,age/3600,str(author),repr(title),repr(item.body)))
|
||||
try:
|
||||
item.mark_read()
|
||||
except Exception,e:
|
||||
log_warn('Failed to mark %s as read: %s' % (item.id,str(e)))
|
||||
return
|
||||
|
||||
age=time.time()-item.created_utc
|
||||
|
@ -155,7 +171,7 @@ class RedditNetwork(Network):
|
|||
line=line.replace(self.keyword,'').strip()
|
||||
if self.on_command:
|
||||
try:
|
||||
parent_item=self.reddit.get_info(thing_id=item.parent_id)
|
||||
parent_item=next(self.reddit.info([item.parent_id]))
|
||||
if not hasattr(parent_item,'author'):
|
||||
raise RuntimeError('Parent item has no author')
|
||||
author=parent_item.author.name
|
||||
|
@ -167,10 +183,11 @@ class RedditNetwork(Network):
|
|||
self.on_command(link,synthetic_cmd)
|
||||
except Exception,e:
|
||||
log_error('Failed to tip %s\'s parent: %s' % (item.id,str(e)))
|
||||
try:
|
||||
item.mark_as_read()
|
||||
except Exception,e:
|
||||
log_warning('Failed to mark %s as read: %s' % (item.id,str(e)))
|
||||
if True:
|
||||
try:
|
||||
item.mark_read()
|
||||
except Exception,e:
|
||||
log_warn('Failed to mark %s as read: %s' % (item.id,str(e)))
|
||||
|
||||
def _schedule_reply(self,item,recipient,text):
|
||||
log_log('scheduling reply to %s:%s: %s' % (item.id if item else '""',recipient or '""',text))
|
||||
|
@ -214,7 +231,10 @@ class RedditNetwork(Network):
|
|||
if fullname in self.items_cache:
|
||||
item=self.items_cache[fullname]
|
||||
if not item:
|
||||
item=self.reddit.get_info(thing_id=fullname)
|
||||
item = self.reddit.mesage(fullname)
|
||||
if not item:
|
||||
gen=self.reddit.info([fullname])
|
||||
item=next(gen, None)
|
||||
if not item:
|
||||
log_error('Failed to find item %s to post %s' % (fullname,text))
|
||||
redis_lpop('reddit:replies')
|
||||
|
@ -226,9 +246,6 @@ class RedditNetwork(Network):
|
|||
|
||||
redis_lpop('reddit:replies')
|
||||
|
||||
except praw.errors.RateLimitExceeded,e:
|
||||
log_info('Rate limited trying to send %s, will retry: %s' % (data,str(e)))
|
||||
return False
|
||||
except Exception,e:
|
||||
log_error('Error sending %s, will retry: %s' % (data,str(e)))
|
||||
return False
|
||||
|
@ -256,15 +273,15 @@ class RedditNetwork(Network):
|
|||
self._parse(message,not message.was_comment)
|
||||
|
||||
else:
|
||||
messages=self.reddit.get_inbox()
|
||||
for message in messages:
|
||||
if not message.was_comment:
|
||||
for message in self.reddit.inbox.unread(limit=self.load_limit):
|
||||
#if not message.was_comment:
|
||||
self._parse(message,True)
|
||||
|
||||
sr=self.reddit.get_subreddit("+".join(self.subreddits))
|
||||
comments=sr.get_comments(limit=self.load_limit)
|
||||
for comment in comments:
|
||||
self._parse(comment,False)
|
||||
#print "Submissions from %s" % ("+".join(self.subreddits))
|
||||
#sr=self.reddit.subreddit("+".join(self.subreddits))
|
||||
#for s in sr.new(limit=self.load_limit):
|
||||
# for comment in s.comments:
|
||||
# self._parse(comment,False)
|
||||
|
||||
while self._post_next_reply():
|
||||
pass
|
||||
|
|
170
tipbot/modules/spammer.py
Normal file
170
tipbot/modules/spammer.py
Normal file
|
@ -0,0 +1,170 @@
|
|||
#!/bin/python
|
||||
#
|
||||
# Cryptonote tipbot - matylda commands
|
||||
# Copyright 2014, 2015 moneromooo
|
||||
#
|
||||
# The Cryptonote tipbot is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as published
|
||||
# by the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
|
||||
import sys
|
||||
import redis
|
||||
import string
|
||||
import re
|
||||
import tipbot.config as config
|
||||
from tipbot.log import log_error, log_warn, log_info, log_log
|
||||
import tipbot.coinspecs as coinspecs
|
||||
from tipbot.utils import *
|
||||
from tipbot.user import User
|
||||
from tipbot.link import Link
|
||||
from tipbot.redisdb import *
|
||||
from tipbot.command_manager import *
|
||||
|
||||
def BanUser(link):
|
||||
log_info('Banning %s (%s)' % (link.user.nick, link.user.ident))
|
||||
if not link.group:
|
||||
return
|
||||
chan=link.group.name
|
||||
log_info("chan: " + chan)
|
||||
net=link.network
|
||||
try:
|
||||
cmd="MODE " + chan + " +b " + link.user.ident
|
||||
net._irc_sendmsg(cmd)
|
||||
cmd="KICK " + chan + " " + link.user.nick
|
||||
net._irc_sendmsg(cmd)
|
||||
except:
|
||||
pass
|
||||
|
||||
def MuteUser(link):
|
||||
log_info('Muting %s (%s)' % (link.user.nick, link.user.ident))
|
||||
if not link.group:
|
||||
return
|
||||
chan=link.group.name
|
||||
log_info("chan: " + chan)
|
||||
net=link.network
|
||||
try:
|
||||
cmd="MODE " + chan + " +q " + link.user.ident
|
||||
net._irc_sendmsg(cmd)
|
||||
except:
|
||||
pass
|
||||
|
||||
def OnUserJoined(event,*args,**kwargs):
|
||||
link=kwargs['link']
|
||||
|
||||
nick=link.user.nick.lower()
|
||||
if nick=="lbft" or nick=="lbft_":
|
||||
BanUser(link)
|
||||
|
||||
triggers=[l.lower() for l in [
|
||||
"triple your btc", "pm me to begin", "hatt uu",
|
||||
"accelerate the blockchain", "u stappid", "me a message to begin",
|
||||
"the ops have confirmed", "expanding technology", "exploding technology",
|
||||
"allah is doing", "pm me to get going", "defragment the blockchain to grow"
|
||||
]]
|
||||
|
||||
def OnMessage(event,*args,**kwargs):
|
||||
line=kwargs['message']
|
||||
if not line:
|
||||
return
|
||||
link=kwargs['link']
|
||||
if IsAdmin(link):
|
||||
return
|
||||
if link.nick in config.allowed:
|
||||
return
|
||||
|
||||
line=re.sub(r'\x03[0-9]?[0-9]?','',line)
|
||||
line=re.sub(r'\x0f','',line)
|
||||
line=line.lower().strip()
|
||||
|
||||
log_info("Testing: " + line)
|
||||
for expr in triggers:
|
||||
if re.match(".*"+expr+".*",line):
|
||||
MuteUser(link)
|
||||
return
|
||||
|
||||
def AddTrigger(link,cmd):
|
||||
triggers.append(" ".join(cmd[1:]))
|
||||
|
||||
def ShowTriggers(link,cmd):
|
||||
link.send(", ".join(triggers))
|
||||
|
||||
def Ban(link,cmd):
|
||||
link.send("disabled") # need to ban by ident
|
||||
return
|
||||
|
||||
try:
|
||||
who=cmd[1]
|
||||
except Exception,e:
|
||||
link.send("usage: ban <nick>")
|
||||
return
|
||||
group=link.group
|
||||
if not group:
|
||||
link.send("Not in a channel")
|
||||
return
|
||||
l=Link(link.network,User(link.network,who),group)
|
||||
BanUser(l)
|
||||
|
||||
def Mute(link,cmd):
|
||||
link.send("disabled") # need to mute by ident
|
||||
return
|
||||
|
||||
try:
|
||||
who=cmd[1]
|
||||
except Exception,e:
|
||||
link.send("usage: mute <nick>")
|
||||
return
|
||||
group=link.group
|
||||
if not group:
|
||||
link.send("Not in a channel")
|
||||
return
|
||||
l=Link(link.network,User(link.network,who),group)
|
||||
MuteUser(l)
|
||||
|
||||
def Help(link):
|
||||
link.send_private('Ban assholes')
|
||||
|
||||
|
||||
RegisterModule({
|
||||
'name': __name__,
|
||||
'help': Help,
|
||||
})
|
||||
RegisterEventHandler({
|
||||
'module': __name__,
|
||||
'event': 'user-joined',
|
||||
'function': OnUserJoined,
|
||||
})
|
||||
RegisterEventHandler({
|
||||
'module': __name__,
|
||||
'event': 'message',
|
||||
'function': OnMessage,
|
||||
})
|
||||
RegisterCommand({
|
||||
'module': __name__,
|
||||
'name': 'add_trigger',
|
||||
'function': AddTrigger,
|
||||
'admin': True,
|
||||
'help': "add keyword trigger to spammer trap"
|
||||
})
|
||||
RegisterCommand({
|
||||
'module': __name__,
|
||||
'name': 'show_triggers',
|
||||
'function': ShowTriggers,
|
||||
'admin': True,
|
||||
'help': "list keyword triggers"
|
||||
})
|
||||
RegisterCommand({
|
||||
'module': __name__,
|
||||
'name': 'ban',
|
||||
'function': Ban,
|
||||
'admin': True,
|
||||
'help': "ban a user"
|
||||
})
|
||||
RegisterCommand({
|
||||
'module': __name__,
|
||||
'name': 'mute',
|
||||
'function': Mute,
|
||||
'admin': True,
|
||||
'help': "mute a user"
|
||||
})
|
|
@ -10,9 +10,10 @@
|
|||
#
|
||||
|
||||
class User:
|
||||
def __init__(self,network,nick):
|
||||
def __init__(self,network,nick,ident=None):
|
||||
self.network=network
|
||||
self.nick=nick
|
||||
self.ident=ident
|
||||
|
||||
def check_registered(self):
|
||||
pass
|
||||
|
|
|
@ -17,6 +17,8 @@ import time
|
|||
import threading
|
||||
import math
|
||||
import string
|
||||
import random
|
||||
from Crypto.Random.random import getrandbits
|
||||
from decimal import *
|
||||
import tipbot.config as config
|
||||
import tipbot.coinspecs as coinspecs
|
||||
|
@ -55,8 +57,10 @@ def GetParam(parms,idx):
|
|||
return parms[idx]
|
||||
return None
|
||||
|
||||
def GetPaymentID(link):
|
||||
def GetPaymentID(link,random=False):
|
||||
salt="2u3g55bkwrui32fi3g4bGR$j5g4ugnujb-"+coinspecs.name+"-";
|
||||
if random:
|
||||
salt = salt + "-" + str(time.time()) + "-" + str(getrandbits(128))
|
||||
p = hashlib.sha256(salt+link.identity()).hexdigest();
|
||||
try:
|
||||
redis_hset("paymentid",p,link.identity())
|
||||
|
@ -64,6 +68,9 @@ def GetPaymentID(link):
|
|||
log_error('GetPaymentID: failed to set payment ID for %s to redis: %s' % (link.identity(),str(e)))
|
||||
return p
|
||||
|
||||
def GetRandomPaymentID(link):
|
||||
return GetPaymentID(link, True)
|
||||
|
||||
def GetIdentityFromPaymentID(p):
|
||||
if not redis_hexists("paymentid",p):
|
||||
log_log('PaymentID %s not found' % p)
|
||||
|
@ -76,8 +83,18 @@ def GetIdentityFromPaymentID(p):
|
|||
identity = "freenode:"+identity
|
||||
return identity
|
||||
|
||||
def IsAddressLengthValid(address):
|
||||
if type(coinspecs.address_length[0]) == list:
|
||||
for allist in coinspecs.address_length:
|
||||
if len(address) >= allist[0] and len(address) <= allist[1]:
|
||||
return True
|
||||
else:
|
||||
if len(address) >= coinspecs.address_length[0] and len(address) <= coinspecs.address_length[1]:
|
||||
return True
|
||||
return False
|
||||
|
||||
def IsValidAddress(address):
|
||||
if len(address) < coinspecs.address_length[0] or len(address) > coinspecs.address_length[1]:
|
||||
if not IsAddressLengthValid(address):
|
||||
return False
|
||||
for prefix in coinspecs.address_prefix:
|
||||
if address.startswith(prefix):
|
||||
|
@ -198,7 +215,7 @@ def StringToUnits(s):
|
|||
|
||||
def SendJSONRPCCommand(host,port,method,params):
|
||||
try:
|
||||
http = httplib.HTTPConnection(host,port,timeout=20)
|
||||
http = httplib.HTTPConnection(host,port,timeout=config.rpc_timeout)
|
||||
except Exception,e:
|
||||
log_error('SendJSONRPCCommand: Error connecting to %s:%u: %s' % (host, port, str(e)))
|
||||
raise
|
||||
|
@ -235,7 +252,7 @@ def SendJSONRPCCommand(host,port,method,params):
|
|||
|
||||
def SendHTMLCommand(host,port,method):
|
||||
try:
|
||||
http = httplib.HTTPConnection(host,port,timeout=20)
|
||||
http = httplib.HTTPConnection(host,port,timeout=config.rpc_timeout)
|
||||
except Exception,e:
|
||||
log_error('SendHTMLCommand: Error connecting to %s:%u: %s' % (host, port, str(e)))
|
||||
raise
|
||||
|
|
Loading…
Reference in a new issue