Beispiel #1
0
def process(com, val):
	"""
	Multiprocessing target. Gets the Markov model, uses it to get a sentence, and posts that as a reply.
	"""
	warnings.simplefilter('ignore')
	if com == None:
		return
	id = com.name
	author = com.author.name if com.author else 'None'
	target_user = val[val.find(' ')+1:]
	with silent():
		r = rlogin.get_auth_r(USER, APP, "2.1", uas="Windows:User Simulator/v0.3 by /u/Trambelus, operating on behalf of %s" % author)
	if target_user[:3] == '/u/':
		target_user = target_user[3:]
	log('%s: started %s for %s on %s' % (id, target_user, author, time.strftime("%Y-%m-%d %X",time.localtime(com.created_utc))))
	model = get_markov(r, id, target_user)
	if isinstance(model, str):
		com.reply(model % target_user)
	else:
		reply_r = model.make_sentence(tries=100)
		if reply_r == None:
			com.reply("Couldn't simulate %s: maybe this user is a bot, or has too few unique comments." % target_user)
			return
		reply = unidecode(reply_r)
		log("%s: Replying:\n%s" % (id, reply))
		com.reply(reply)
	log('%s: Finished' % id)
Beispiel #2
0
def monitor():
    """
	Main loop. Looks through username notifications, comment replies, and whatever else,
	and launches a single process for every new request it finds.
	"""
    get_r = lambda: rlogin.get_auth_r(USER, APP, VERSION, uas="Windows:User Simulator/v%s by /u/Trambelus, main thread" % VERSION)

    started = []
    q = mp.Queue()
    quit_proc = mp.Process(target=wait, args=(q, ))
    quit_proc.start()
    req_pat = re.compile(
        r"\+(\s)?/u/%s\s?(\[.\])?\s+(/u/)?[\w\d\-_]{3,20}" % USER.lower())
    with silent():
        r = get_r()
    t0 = time.time()
    log('Restarted')
    while True:
        try:
            # Every 55 minutes, refresh the login.
            if (time.time() - t0 > 55 * 60):
                with silent():
                    r = get_r()
                log("Refreshed login")
                t0 = time.time()
            mentions = r.get_inbox()
            for com in mentions:
                res = re.search(req_pat, com.body.lower())
                if res == None:
                    continue  # We were mentioned but it's not a proper request, move on
                try:
                    if USER.lower() in [
                            rep.author.name.lower() for rep in com.replies
                            if rep.author != None
                    ]:
                        continue  # We've already hit this one, move on
                except praw.errors.Forbidden:
                    continue
                if com.name in started:
                    continue  # We've already started on this one, move on
                started.append(com.name)
                warnings.simplefilter("ignore")
                mp.Process(target=process, args=(q, com, res.group(0))).start()
            if not quit_proc.is_alive():
                log("Stopping main process")
                return
            while q.qsize() > 0:
                item = q.get()
                if item == 'clear':
                    log("Clearing list of started tasks")
                    started = []
                elif item in started:
                    started.remove(item)
            time.sleep(1)
        # General-purpose catch to make the script unbreakable.
        except praw.errors.InvalidComment:
            continue  # This one was completely trashing the console, so handle it silently.
        except Exception as ex:
            log(str(type(ex)) + ": " + str(ex))
Beispiel #3
0
def get_user_top(sort):
	r = rlogin.get_auth_r(USER, APP, VERSION, uas="Windows:User Simulator/v%s by /u/Trambelus, updating local user cache" % VERSION)
	redditor = r.get_redditor(USER)
	comments = redditor.get_comments(limit=None, sort=sort)
	for c in comments:
		print("%s at %s in %s: %s" % (c.name, dfmt(c.created_utc), c.subreddit.display_name, c.score))
		with open("%s.txt" % sort,"a") as f:
			f.write(c.name + '\n')
Beispiel #4
0
def process(q, com, val):
	"""
	Multiprocessing target. Gets the Markov model, uses it to get a sentence, and posts that as a reply.
	"""
	warnings.simplefilter('ignore')
	if com == None:
		return
	id = com.name
	author = com.author.name if com.author else 'None'
	sub = com.subreddit.display_name
	val = val.replace('\n',' ')
	val = val.replace('\t',' ')
	val = val.replace(chr(160),' ')
	target_user = val[val.rfind(' ')+1:].strip()
	if author.lower() in NO_REPLY:
		com.reply("I see what you're trying to do.%s" % get_footer())
		return
	if ('+/u/%s' % USER).lower() in target_user.lower():
		com.reply("User '%s' appears to have broken the bot. That is not nice, %s.%s" % (author,author,get_footer()))
		return
	idx = com.body.lower().find(target_user.lower())
	target_user = com.body[idx:idx+len(target_user)]
	with silent():
		r = rlogin.get_auth_r(USER, APP, VERSION, uas="Windows:User Simulator/v%s by /u/Trambelus, operating on behalf of %s" % (VERSION,author))
	if target_user[:3] == '/u/':
		target_user = target_user[3:]
	#log('%s: Started %s for %s on %s' % (id, target_user, author, time.strftime("%Y-%m-%d %X",time.localtime(com.created_utc))))
	(model, sentence_avg) = get_markov(r, id, target_user)
	try:
		if isinstance(model, str):
			com.reply((model % target_user) + get_footer())
			log('%s by %s in %s on %s:\n%s\n' % (target_user, author, com.subreddit.display_name, time.strftime("%Y-%m-%d %X",time.localtime(com.created_utc)), model % target_user))
		else:
			reply_r = []
			for _ in range(sentence_avg):
				tmp_s = model.make_sentence(tries=TRIES)
				if tmp_s == None:
					com.reply("Couldn't simulate %s: maybe this user is a bot, or has too few unique comments.%s" % (target_user,get_footer()))
					return
				reply_r.append(tmp_s)
			if sentence_avg == 0:
				com.reply("Couldn't simulate %s: maybe this user is a bot, or has too few unique comments.%s" % (target_user,get_footer()))
				return
			reply_r = ' '.join(reply_r)
			reply = unidecode(reply_r)
			if com.subreddit.display_name == 'EVEX':
				target_user = target_user + random.choice(['-senpai','-kun','-chan','-san','-sama'])
			log('%s (%d) by %s in %s on %s, reply:\n%s\n' % (target_user, sentence_avg, author, sub, time.strftime("%Y-%m-%d %X",time.localtime(com.created_utc)), reply))
			com.reply('%s\n\n ~ %s%s' % (reply,target_user,get_footer()))
		#log('%s: Finished' % id)
	except praw.errors.RateLimitExceeded as ex:
		log(id + ": Rate limit exceeded: " + str(ex))
		q.put(id)
	except praw.errors.Forbidden:
		log("Could not reply to comment by %s in %s" % (author, sub))
	except praw.errors.APIException:
		log("Parent comment by %s in %s was deleted" % (author, sub))
Beispiel #5
0
def open_by_id(id):
    import webbrowser
    r = rlogin.get_auth_r(
        USER,
        APP,
        VERSION,
        uas="%s:User Simulator/v%s by /u/Trambelus, updating local user cache"
        % (platform.system(), VERSION))
    webbrowser.open_new_tab(r.get_info(thing_id=id).permalink)
Beispiel #6
0
def monitor_sub(q, index):
    started = []
    get_r = lambda: rlogin.get_auth_r(
        USER,
        APP,
        VERSION,
        uas="Windows:User Simulator/v%s by /u/Trambelus, main thread %d" %
        (VERSION, index))
    req_pat = re.compile(r"\+(\s)?/u/%s\s?(\[.\])?\s+(/u/)?[\w\d\-_]{3,20}" %
                         USER.lower())
    with silent():
        r = get_r()
    t0 = time.time()
    log('Started main thread %d' % (index + 1))
    while True:
        try:
            # Every 55 minutes, refresh the login.
            if (time.time() - t0 > 55 * 60):
                with silent():
                    r = get_r()
                log("Refreshed login")
                t0 = time.time()
            mentions = r.get_inbox(limit=INBOX_LIMIT)
            for com in mentions:
                if int(com.name[3:], 36) % MONITOR_PROCESSES != index:
                    continue
                res = re.search(req_pat, com.body.lower())
                if res == None:
                    continue  # We were mentioned but it's not a proper request, move on
                try:
                    if USER.lower() in [
                            rep.author.name.lower() for rep in com.replies
                            if rep.author != None
                    ]:
                        continue  # We've already hit this one, move on
                except praw.errors.Forbidden:
                    continue
                if com.name in started:
                    continue  # We've already started on this one, move on
                started.append(com.name)
                warnings.simplefilter("ignore")
                mp.Process(target=process, args=(q, com, res.group(0))).start()
            while q.qsize() > 0:
                item = q.get()
                if item == 'clear':
                    log("Clearing list of started tasks")
                    started = []
                elif item == 'quit':
                    log("Stopping main process")
                    return
                elif item in started:
                    started.remove(item)
        # General-purpose catch to make the script unbreakable.
        except praw.errors.InvalidComment:
            continue  # This one was completely trashing the console, so handle it silently.
        except Exception as ex:
            log(str(type(ex)) + ": " + str(ex))
Beispiel #7
0
def monitor():
	"""
	Main loop. Looks through username notifications, comment replies, and whatever else,
	and launches a single process for every new request it finds.
	"""
	started = []
	q = mp.Queue()
	quit_proc = mp.Process(target=wait, args=(q,))
	quit_proc.start()
	req_pat = re.compile(r"\+/u/%s\s(/u/)?[\w\d\-_]{3,20}" % USER.lower())
	r = rlogin.get_auth_r(USER, APP)
	t0 = time.time()
	log('Restarted')
	while True:
		try:
			# Every 55 minutes, refresh the login.
			if (time.time() - t0 > 55*60):
				r = rlogin.get_auth_r(USER, APP)
				t0 = time.time()
			mentions = r.get_inbox()
			for com in mentions:
				if com.author == None:
					continue # Extreme edge case: they deleted their comment before the reply could process
				res = re.search(req_pat, com.body.lower())
				if res == None:
					continue # We were mentioned but it's not a proper request, move on
				if USER in [rep.author.name for rep in com.replies if rep.author != None]:
					continue # We've already hit this one, move on
				if com.name in started:
					continue # We've already started on this one, move on
				started.append(com.name)
				warnings.simplefilter("ignore")
				mp.Process(target=process, args=(com, res.group(0))).start()
			if not quit_proc.is_alive():
				log("Quitting")
				return
			if q.qsize() > 0:
				if q.get() == 'clear':
					started = []
			time.sleep(1)
		# General-purpose catch to make the script unbreakable.
		except Exception as ex:
			log("Error in main process: %s" % ex)
Beispiel #8
0
def count(user):
    r = rlogin.get_auth_r(
        USER,
        APP,
        VERSION,
        uas="%s:User Simulator/v%s by /u/Trambelus, counting comments of %s" %
        (platform.system(), VERSION, user))
    (history, num_comments, sentence_avg) = get_history(r, user)
    print("{}: {} comments, average {:.3f} sentences per comment".format(
        user, num_comments, sentence_avg))
Beispiel #9
0
def open_by_id(id):
    import webbrowser
    r = rlogin.get_auth_r(
        USER,
        APP,
        VERSION,
        uas="%s:User Simulator/v%s by /u/Trambelus, updating local user cache"
        % (platform.system(), VERSION))
    webbrowser.open_new_tab("http://www.reddit.com{}".format(
        r.comment(id).context))
Beispiel #10
0
def count(user):
    with silent():
        r = rlogin.get_auth_r(
            USER,
            APP,
            VERSION,
            uas=
            "Windows:User Simulator/v%s by /u/Trambelus, counting comments of %s"
            % (VERSION, user))
    history = get_history(r, user)
    print("{}: {} comments".format(user, len(history)))
Beispiel #11
0
def upgrade():
	files = [f[:-4] for f in os.listdir(USERMOD_DIR) if f[-4:] == '.txt']
	r = rlogin.get_auth_r(USER, APP, VERSION, uas="Windows:User Simulator/v%s by /u/Trambelus, upgrading cache" % VERSION)
	for user in files:
		info_fname = USERMOD_DIR + user + '.info'
		if os.path.isfile(info_fname):
			continue
		(history, num_comments, sentence_avg) = get_history(r, user)
		print("%s: average %d across %d comments" % (user, int(sentence_avg), num_comments))
		with open(info_fname, 'w') as f:
			f.write(str(int(sentence_avg)))
Beispiel #12
0
def manual(user, num):
	"""
	This allows the script to be invoked like this:
	usim.py manual some-reddit-user
	This was useful for when the script failed to reply in some cases.
	I logged in as the script, got a manual response like this,
	and just pasted it in as a normal comment.
	They never knew.
	Don't tell them.
	"""
	r = rlogin.get_auth_r(USER, APP, VERSION, uas="%s:User Simulator/v%s by /u/Trambelus, operating in manual mode" % (platform.system(),VERSION))
	(model, sentence_avg) = get_markov(r, 'manual', user)
	print(' '.join([unidecode(model.make_sentence()) for i in range(sentence_avg)]))
Beispiel #13
0
def get_user_top(sort):
    r = rlogin.get_auth_r(
        USER,
        APP,
        VERSION,
        uas="%s:User Simulator/v%s by /u/Trambelus, updating local user cache"
        % (platform.system(), VERSION))
    redditor = r.get_redditor(USER)
    comments = redditor.get_comments(limit=None, sort=sort)
    for c in comments:
        print("%s at %s in %s: %s" %
              (c.name, dfmt(c.created_utc), c.subreddit.display_name, c.score))
        with open("%s.txt" % sort, "a") as f:
            f.write(c.name + '\n')
Beispiel #14
0
def manual(user, num):
	"""
	This allows the script to be invoked like this:
	usim.py manual some-reddit-user
	This was useful for when the script failed to reply in some cases.
	I logged in as the script, got a manual response like this,
	and just pasted it in as a normal comment.
	They never knew.
	Don't tell them.
	"""
	with silent():
		r = rlogin.get_auth_r(USER, APP, VERSION, uas="Windows:User Simulator/v%s by /u/Trambelus, operating in manual mode" % VERSION)
	model = get_markov(r, 'manual', user)
	log(unidecode(model.make_sentence()))
Beispiel #15
0
def get_banned():
	r = rlogin.get_auth_r(USER, APP, VERSION, uas="%s:User Simulator/v%s by /u/Trambelus, updating local user cache" % (platform.system(),VERSION))
	with open(BANNED_FILE, 'r') as f:
		banned = [s.rstrip() for s in f.readlines()]
	c = 0
	with open("bancount.txt", 'w') as f:
		for sub in banned:
			try:
				b = r.get_subreddit(sub).subscribers
				c += b
			except praw.errors.Forbidden:
				b = "Unknown"
			f.write("%s: %s\n" % (sub, b))
		f.write("----------------\nTotal: %d" % c)
	print("Banned from %d subs, %d subscribers" % len(banned), c)
Beispiel #16
0
def monitor_sub(q, index):
	started = []
	get_r = lambda: rlogin.get_auth_r(USER, APP, VERSION, uas="Windows:User Simulator/v%s by /u/Trambelus, main thread %d" % (VERSION, index))
	req_pat = re.compile(r"\+(\s)?/u/%s\s?(\[.\])?\s+(/u/)?[\w\d\-_]{3,20}" % USER.lower())
	with silent():
		r = get_r()
	t0 = time.time()
	log('Started main thread %d' % (index+1))
	while True:
		try:
			# Every 55 minutes, refresh the login.
			if (time.time() - t0 > 55*60):
				with silent():
					r = get_r()
				log("Refreshed login")
				t0 = time.time()
			mentions = r.get_inbox(limit=INBOX_LIMIT)
			for com in mentions:
				if int(com.name[3:], 36) % MONITOR_PROCESSES != index:
					continue
				res = re.search(req_pat, com.body.lower())
				if res == None:
					continue # We were mentioned but it's not a proper request, move on
				try:
					if USER.lower() in [rep.author.name.lower() for rep in com.replies if rep.author != None]:
						continue # We've already hit this one, move on
				except praw.errors.Forbidden:
					continue
				if com.name in started:
					continue # We've already started on this one, move on
				started.append(com.name)
				warnings.simplefilter("ignore")
				mp.Process(target=process, args=(q, com, res.group(0))).start()
			while q.qsize() > 0:
				item = q.get()
				if item == 'clear':
					log("Clearing list of started tasks")
					started = []
				elif item == 'quit':
					log("Stopping main process")
					return
				elif item in started:
					started.remove(item)
		# General-purpose catch to make the script unbreakable.
		except praw.errors.InvalidComment:
			continue # This one was completely trashing the console, so handle it silently.
		except Exception as ex:
			log(str(type(ex)) + ": " + str(ex))
Beispiel #17
0
def upgrade():
    files = [f[:-4] for f in os.listdir(USERMOD_DIR) if f[-4:] == '.txt']
    r = rlogin.get_auth_r(
        USER,
        APP,
        VERSION,
        uas="Windows:User Simulator/v%s by /u/Trambelus, upgrading cache" %
        VERSION)
    for user in files:
        info_fname = USERMOD_DIR + user + '.info'
        if os.path.isfile(info_fname):
            continue
        (history, num_comments, sentence_avg) = get_history(r, user)
        print("%s: average %d across %d comments" %
              (user, int(sentence_avg), num_comments))
        with open(info_fname, 'w') as f:
            f.write(str(int(sentence_avg)))
Beispiel #18
0
def manual(user, num):
    """
	This allows the script to be invoked like this:
	usim.py manual some-reddit-user
	This was useful for when the script failed to reply in some cases.
	I logged in as the script, got a manual response like this,
	and just pasted it in as a normal comment.
	They never knew.
	Don't tell them.
	"""
    r = rlogin.get_auth_r(
        USER,
        APP,
        VERSION,
        uas="%s:User Simulator/v%s by /u/Trambelus, operating in manual mode"
        % (platform.system(), VERSION),
    )
    (model, sentence_avg) = get_markov(r, "manual", user)
    print(" ".join([unidecode(model.make_sentence()) for i in range(sentence_avg)]))
Beispiel #19
0
def manual(user, num):
    """
	This allows the script to be invoked like this:
	usim.py manual some-reddit-user
	This was useful for when the script failed to reply in some cases.
	I logged in as the script, got a manual response like this,
	and just pasted it in as a normal comment.
	They never knew.
	Don't tell them.
	"""
    with silent():
        r = rlogin.get_auth_r(
            USER,
            APP,
            VERSION,
            uas=
            "Windows:User Simulator/v%s by /u/Trambelus, operating in manual mode"
            % VERSION)
    model = get_markov(r, 'manual', user)
    log(unidecode(model.make_sentence()))
Beispiel #20
0
def get_banned():
    r = rlogin.get_auth_r(
        USER,
        APP,
        VERSION,
        uas="%s:User Simulator/v%s by /u/Trambelus, updating local user cache"
        % (platform.system(), VERSION))
    with open(BANNED_FILE, 'r') as f:
        banned = [s.rstrip() for s in f.readlines()]
    c = 0
    with open("bancount.txt", 'w') as f:
        for sub in banned:
            try:
                b = r.get_subreddit(sub).subscribers
                c += b
            except praw.errors.Forbidden:
                b = "Unknown"
            f.write("%s: %s\n" % (sub, b))
        f.write("----------------\nTotal: %d" % c)
    print("Banned from %d subs, %d subscribers" % len(banned), c)
Beispiel #21
0
def upgrade():
    files = [f[:-4] for f in os.listdir(USERMOD_DIR) if f[-4:] == ".txt"]
    r = rlogin.get_auth_r(
        USER,
        APP,
        VERSION,
        uas="%s:User Simulator/v%s by /u/Trambelus, upgrading cache"
        % (platform.system(), VERSION),
    )
    for user in files:
        info_fname = os.path.join(USERMOD_DIR, user + ".info")
        if os.path.isfile(info_fname):
            continue
        (history, num_comments, sentence_avg) = get_history(r, user)
        print(
            "%s: average %d across %d comments"
            % (user, int(sentence_avg), num_comments)
        )
        with open(info_fname, "w") as f:
            f.write(str(int(sentence_avg)))
Beispiel #22
0
def main():
	# Holds every line of the file
	file_strs = []
	# Import file
	with open(os.path.join(sys.path[0],LIST_PATH),'r') as f:
		file_strs = [s.rstrip() for s in f.readlines()]
	# Get local current time in struct_time (tuple) format
	lt = time.localtime()
	# Compare date portion of tuple to what's in the file
	if lt[:3] == tuple(map(int,file_strs[0].split('-'))):
		print("Already posted today; exiting")
		return
	# Obtain Reddit and subreddit from praw via rlogin
	r = rlogin.get_auth_r(USER, APP)
	sub = r.get_subreddit(SUB)
	# Which Bloom are we on today?
	index = int(file_strs[1])
	# Trim list to submissions only; separate titles and URLs 
	submissions = [s.split('\t') for s in file_strs[2:]]
	# If we've gone through all the file entries, exit.
	if len(submissions) <= index-3:
		print("No submissions left in file!")
		return
	# Construct post title
	title = submissions[index-3][0]
	if INCLUDE_POST_NUMS:
		title = 'Daily Bloom #%d: %s' % (index, submissions[index-3][0])
	url = submissions[index-3][1]
	# Print to confirm
	print(title)
	print(url)
	# Update information to put back in the file
	file_strs[1] = str(index+1)
	file_strs[0] = time.strftime('%Y-%m-%d')
	# The big line. Submit to the PLounge.
	submission = r.submit(sub, title, url=url, send_replies=True)
	# Writeback
	with open(LIST_PATH,'w') as f:
		f.write('\n'.join(file_strs))
	r.select_flair(submission, '20154dac-1ea8-11e5-8d27-0ef6ca535a4d', FLAIR)
Beispiel #23
0
def count(user):
	with silent():
		r = rlogin.get_auth_r(USER, APP, VERSION, uas="Windows:User Simulator/v%s by /u/Trambelus, counting comments of %s" % (VERSION,user))
	history = get_history(r, user)
	print("{}: {} comments".format(user, len(history)))
Beispiel #24
0
def process(q, com, val):
    """
	Multiprocessing target. Gets the Markov model, uses it to get a sentence, and posts that as a reply.
	"""
    warnings.simplefilter('ignore')
    if com == None:
        return
    id = com.name
    author = com.author.name if com.author else '[deleted]'
    sub = com.subreddit.display_name
    ctime = time.strftime("%Y-%m-%d %X", time.localtime(com.created_utc))
    val = val.replace('\n', ' ')
    val = val.replace('\t', ' ')
    val = val.replace(chr(160), ' ')
    target_user = val[val.rfind(' ') + 1:].strip()
    if author.lower() in NO_REPLY:
        try_reply(com, "I see what you're trying to do.%s" % get_footer())
        return
    if ('+/u/%s' % USER).lower() in target_user.lower():
        try_reply(
            q, com,
            "User '%s' appears to have broken the bot. That is not nice, %s.%s"
            % (author, author, get_footer()))
        return
    idx = com.body.lower().find(target_user.lower())
    target_user = com.body[idx:idx + len(target_user)]
    with silent():
        r = rlogin.get_auth_r(
            USER,
            APP,
            VERSION,
            uas=
            "Windows:User Simulator/v%s by /u/Trambelus, operating on behalf of %s"
            % (VERSION, author))
    if target_user[:3] == '/u/':
        target_user = target_user[3:]
    if target_user == 'YOURUSERNAMEHERE':
        log("Corrected 'YOURUSERNAMEHERE' to %s" % author)
        target_user = author
    #log('%s: Started %s for %s on %s' % (id, target_user, author, time.strftime("%Y-%m-%d %X",time.localtime(com.created_utc))))
    try:
        next(r.get_redditor(target_user).get_comments(limit=1))
    except praw.errors.NotFound:
        if levenshteinDistance(target_user, author) < 3:
            log("Corrected spelling from %s to %s" % (target_user, author))
            target_user = author
    except StopIteration:
        pass
    except praw.errors.HTTPException:
        time.sleep(1)
    (model, sentence_avg) = get_markov(r, id, target_user)
    try:
        if isinstance(model, str):
            try_reply(q, com, (model % target_user) + get_footer())
            log('%s: %s by %s in %s on %s:\n%s' %
                (id, target_user, author, sub, ctime, model % target_user),
                additional='\n')
        else:
            if sentence_avg == 0:
                try_reply(
                    q, com,
                    "Couldn't simulate %s: maybe this user is a bot, or has too few unique comments.%s"
                    % (target_user, get_footer()))
                return
            reply_r = []
            for _ in range(random.randint(1, sentence_avg * 2)):
                tmp_s = model.make_sentence(tries=TRIES)
                if tmp_s == None:
                    try_reply(
                        q, com,
                        "Couldn't simulate %s: maybe this user is a bot, or has too few unique comments.%s"
                        % (target_user, get_footer()))
                    return
                reply_r.append(tmp_s)
            reply_r = ' '.join(reply_r)
            reply = unidecode(reply_r)
            if com.subreddit.display_name == 'EVEX':
                target_user = target_user + random.choice(
                    ['-senpai', '-kun', '-chan', '-san', '-sama'])
            log('%s: %s (%d) by %s in %s on %s, reply' %
                (id, target_user, sentence_avg, author, sub, ctime),
                additional='\n%s\n' % reply)
            target_user = target_user.replace('_', '\_')
            try_reply(q, com,
                      '%s\n\n ~ %s%s' % (reply, target_user, get_footer()))
        #log('%s: Finished' % id)
    except praw.errors.RateLimitExceeded as ex:
        log("%s: %s (%d) by %s in %s on %s: rate limit exceeded: %s" %
            (id, target_user, sentence_avg, author, sub, ctime, str(ex)))
        q.put(id)
    except praw.errors.Forbidden:
        log("Could not reply to comment by %s in %s" % (author, sub))
    except praw.errors.APIException:
        log("Parent comment by %s in %s was deleted" % (author, sub))
    except praw.errors.HTTPException:
        log("%s: %s (%d) by %s in %s on %s: could not reply, will retry: %s" %
            (id, target_user, sentence_avg, author, sub, ctime, str(ex)))
        q.put(id)
Beispiel #25
0
def open_by_id(id):
	import webbrowser
	r = rlogin.get_auth_r(USER, APP, VERSION, uas="Windows:User Simulator/v%s by /u/Trambelus, updating local user cache" % VERSION)
	webbrowser.open_new_tab(r.get_info(thing_id=id).permalink)
Beispiel #26
0
def process(q, com, val, index, r=None):
    """
	Multiprocessing target. Gets the Markov model, uses it to get a sentence, and posts that as a reply.
	"""
    warnings.simplefilter("ignore")
    if com == None:
        return
    id = com.name
    author = com.author.name if com.author else "[deleted]"
    if r is None:
        r = rlogin.get_auth_r(
            USER,
            APP,
            VERSION,
            uas="%s:User Simulator/v%s by /u/Trambelus, operating on behalf of %s"
            % (platform.system(), VERSION, author),
        )

    if com == None:
        return
    sub = com.subreddit.display_name
    ctime = time.strftime("%Y-%m-%d %X", time.localtime(com.created_utc))
    val = val.replace("\n", " ")
    val = val.replace("\t", " ")
    val = val.replace(chr(160), " ")
    target = val[val.rfind(" ") + 1 :].strip()
    if author.lower() in NO_REPLY:
        try_reply(com, "I see what you're trying to do.%s" % FOOTER)
        return
    if ("+/u/%s" % USER).lower() in target.lower():
        try_reply(
            com,
            "User '%s' appears to have broken the bot. That is not nice, %s.%s"
            % (author, author, FOOTER),
        )
        return
    idx = com.body.lower().find(target.lower())
    target = com.body[idx : idx + len(target)]
    r_subreddit = re.compile(r"/?r/[\w\d_]{0,21}")
    if target[:2] == "u/":
        target = target[2:]  # ugly but it works
    if target[:3] == "/u/":
        target = target[3:]
    if target == "YOURUSERNAMEHERE":
        log("Corrected 'YOURUSERNAMEHERE' to %s" % author)
        target = author
    # log('%s: Started %s for %s on %s' % (id, target, author, time.strftime("%Y-%m-%d %X",time.localtime(com.created_utc))))
    try:
        if target[:3] != "/r/":
            next(r.redditor(target).comments.new(limit=1))
    except prawcore.exceptions.NotFound:
        if levenshteinDistance(target, author) < 3:
            log("Corrected spelling from %s to %s" % (target, author))
            target = author
    except StopIteration:
        pass
    except praw.exceptions.APIException:
        time.sleep(1)
    (model, sentence_avg) = get_markov(r, id, target)
    try:
        if isinstance(model, str):
            try_reply(com, (model % target) + FOOTER)
            log(
                "%s: (%d) %s by %s in %s on %s:\n%s"
                % (id, index, target, author, sub, ctime, model % target),
                additional="\n",
            )
        else:
            if sentence_avg == 0:
                try_reply(
                    com,
                    "Couldn't simulate %s: maybe this user is a bot, or has too few unique comments.%s"
                    % (target, FOOTER),
                )
                return
            reply_r = []
            for _ in range(random.randint(1, sentence_avg)):
                tmp_s = model.make_sentence(tries=TRIES)
                if tmp_s == None:
                    try_reply(
                        com,
                        "Couldn't simulate %s: maybe this user is a bot, or has too few unique comments.%s"
                        % (target, FOOTER),
                    )
                    return
                reply_r.append(tmp_s)
            reply_r = " ".join(reply_r)
            reply = unidecode(reply_r)
            if com.subreddit.display_name == "EVEX":
                target = target + random.choice(
                    ["-senpai", "-kun", "-chan", "-san", "-sama"]
                )
            log(
                "%s: (%d) %s (%d) by %s in %s on %s, reply"
                % (id, index, target, sentence_avg, author, sub, ctime),
                additional="\n%s\n" % reply,
            )
            if target[:3] != "/r/":
                target = target.replace("_", "\_")
            try_reply(com, "%s\n\n ~ %s%s" % (reply, target, FOOTER))
        # log('%s: Finished' % id)
    except prawcore.exceptions.Forbidden as ex:
        log("Could not reply to comment by %s in %s: %s" % (author, sub, str(ex)))
    except prawcore.exceptions.APIException:
        log("Parent comment by %s in %s was deleted" % (author, sub))
    except prawcore.exceptions.PrawcoreException as ex:
        log(
            "%s: (%d) %s (%d) by %s in %s on %s: could not reply, will retry: %s"
            % (id, index, target, sentence_avg, author, sub, ctime, str(ex))
        )
        q.put(id)
Beispiel #27
0
def count(user):
	with silent():
		r = rlogin.get_auth_r(USER, APP, VERSION, uas="Windows:User Simulator/v%s by /u/Trambelus, counting comments of %s" % (VERSION,user))
	(history, num_comments, sentence_avg) = get_history(r, user)
	print("{}: {} comments, average {:.3f} sentences per comment".format(user, num_comments, sentence_avg))
Beispiel #28
0
def monitor_sub(q, index):

    started = []
    with open(BANNED_FILE, "r") as f:
        banned = [s.rstrip() for s in f.readlines()]
    get_r = lambda: rlogin.get_auth_r(
        USER,
        APP,
        VERSION,
        uas="%s:User Simulator/v%s by /u/Trambelus, main thread %d"
        % (platform.system(), VERSION, index),
    )
    req_pat = re.compile(
        r"\+(\s)?/?u/%s\s?(\[.\])?\s+(/?(u|r)/)?[\w\d\-_]{3,32}" % USER.lower()
    )
    r = get_r()
    t0 = time.time()
    log("Started main thread %d" % (index + 1))
    while True:
        log("Restarting loop", console_only=True)
        try:
            # Every 55 minutes, refresh the login.
            if time.time() - t0 > 55 * 60:
                r = get_r()
                log("Refreshed login for thread %d" % (index + 1))
                t0 = time.time()
            mentions = r.inbox.all()
            for com in mentions:
                if com.author and com.author.name.lower() in ABSOLUTELY_NO_REPLY:
                    continue  # Some joker set AutoModerator to constantly call the bot
                if int(com.name[3:], 36) % MONITOR_PROCESSES != index:
                    continue  # One of the other monitor threads is handling this one; skip
                if com.name in started:
                    continue  # We've already started on this one, move on
                started.append(com.name)
                try:
                    if com.subreddit == None:
                        continue
                    if com.subreddit.display_name in banned:
                        log(
                            "%s: (%d) Ignored request from banned subreddit %s"
                            % (com.name, index + 1, com.subreddit.display_name)
                        )
                        continue
                except prawcore.exceptions.Forbidden:
                    continue
                res = re.search(req_pat, com.body.lower())
                if res == None:
                    continue  # We were mentioned but it's not a proper request, move on
                try:
                    if USER.lower() in [
                        rep.author.name.lower()
                        for rep in com.replies.list()
                        if rep.author != None
                    ]:
                        continue  # We've already hit this one, move on
                except prawcore.exceptions.Forbidden:
                    continue

                warnings.simplefilter("ignore")
                try:
                    log("%s: processing" % (com.name), console_only=True)
                    # mp.Process(target=process, args=(q, com, res.group(0), index+1)).start()
                    process(q, com, res.group(0), index + 1, r)
                except Exception as ex:
                    log("%s: exception: %s" % (com.name, ex))
                    continue
                while q.qsize() > 0:
                    item = q.get()
                    if item == "clear":
                        log("Clearing list of started tasks")
                        started = []
                    elif item == "quit":
                        log("Stopping main process")
                        return
                    elif item in started:
                        started.remove(item)

                time.sleep(1)

        except AssertionError:
            r = get_r()
            continue
        # General-purpose catch to make the script unbreakable.
        except Exception as ex:
            log(str(index + 1) + ": " + str(type(ex)) + ": " + str(ex))
            time.sleep(1)
            continue
Beispiel #29
0
def process(q, com, val):
	"""
	Multiprocessing target. Gets the Markov model, uses it to get a sentence, and posts that as a reply.
	"""
	warnings.simplefilter('ignore')
	if com == None:
		return
	id = com.name
	author = com.author.name if com.author else '[deleted]'
	sub = com.subreddit.display_name
	ctime = time.strftime("%Y-%m-%d %X",time.localtime(com.created_utc))
	val = val.replace('\n',' ')
	val = val.replace('\t',' ')
	val = val.replace(chr(160),' ')
	target_user = val[val.rfind(' ')+1:].strip()
	if author.lower() in NO_REPLY:
		try_reply(com,"I see what you're trying to do.%s" % get_footer())
		return
	if ('+/u/%s' % USER).lower() in target_user.lower():
		try_reply(q, com,"User '%s' appears to have broken the bot. That is not nice, %s.%s" % (author,author,get_footer()))
		return
	idx = com.body.lower().find(target_user.lower())
	target_user = com.body[idx:idx+len(target_user)]
	with silent():
		r = rlogin.get_auth_r(USER, APP, VERSION, uas="Windows:User Simulator/v%s by /u/Trambelus, operating on behalf of %s" % (VERSION,author))
	if target_user[:3] == '/u/':
		target_user = target_user[3:]
	if target_user == 'YOURUSERNAMEHERE':
		log("Corrected 'YOURUSERNAMEHERE' to %s" % author)
		target_user = author
	#log('%s: Started %s for %s on %s' % (id, target_user, author, time.strftime("%Y-%m-%d %X",time.localtime(com.created_utc))))
	try:
		next(r.get_redditor(target_user).get_comments(limit=1))
	except praw.errors.NotFound:
		if levenshteinDistance(target_user, author) <3:
			log("Corrected spelling from %s to %s" % (target_user, author))
			target_user = author
	except StopIteration:
		pass
	except praw.errors.HTTPException:
		time.sleep(1)
	(model, sentence_avg) = get_markov(r, id, target_user)
	try:
		if isinstance(model, str):
			try_reply(q, com,(model % target_user) + get_footer())
			log('%s: %s by %s in %s on %s:\n%s' % (id, target_user, author, sub, ctime, model % target_user), additional='\n')
		else:
			if sentence_avg == 0:
				try_reply(q, com,"Couldn't simulate %s: maybe this user is a bot, or has too few unique comments.%s" % (target_user,get_footer()))
				return
			reply_r = []
			for _ in range(random.randint(1,sentence_avg*2)):
				tmp_s = model.make_sentence(tries=TRIES)
				if tmp_s == None:
					try_reply(q, com,"Couldn't simulate %s: maybe this user is a bot, or has too few unique comments.%s" % (target_user,get_footer()))
					return
				reply_r.append(tmp_s)
			reply_r = ' '.join(reply_r)
			reply = unidecode(reply_r)
			if com.subreddit.display_name == 'EVEX':
				target_user = target_user + random.choice(['-senpai','-kun','-chan','-san','-sama'])
			log('%s: %s (%d) by %s in %s on %s, reply' % (id, target_user, sentence_avg, author, sub, ctime), additional='\n%s\n' % reply)
			target_user = target_user.replace('_','\_')
			try_reply(q, com,'%s\n\n ~ %s%s' % (reply,target_user,get_footer()))
		#log('%s: Finished' % id)
	except praw.errors.RateLimitExceeded as ex:
		log("%s: %s (%d) by %s in %s on %s: rate limit exceeded: %s" % (id, target_user, sentence_avg, author, sub, ctime, str(ex)))
		q.put(id)
	except praw.errors.Forbidden:
		log("Could not reply to comment by %s in %s" % (author, sub))
	except praw.errors.APIException:
		log("Parent comment by %s in %s was deleted" % (author, sub))
	except praw.errors.HTTPException:
		log("%s: %s (%d) by %s in %s on %s: could not reply, will retry: %s" % (id, target_user, sentence_avg, author, sub, ctime, str(ex)))
		q.put(id)
Beispiel #30
0
def monitor_sub(q, index):

	started = []
	with open(BANNED_FILE, 'r') as f:
		banned = [s.rstrip() for s in f.readlines()]
	get_r = lambda: rlogin.get_auth_r(USER, APP, VERSION, uas="%s:User Simulator/v%s by /u/Trambelus, main thread %d" % (platform.system(),VERSION, index))
	req_pat = re.compile(r"\+(\s)?/u/%s\s?(\[.\])?\s+(/u/)?[\w\d\-_]{3,20}" % USER.lower())
	r = get_r()
	t0 = time.time()
	log('Started main thread %d' % (index+1))
	while True:
		log("Restarting loop", console_only=True)
		try:
			# Every 55 minutes, refresh the login.
			if (time.time() - t0 > 55*60):
				r = get_r()
				log("Refreshed login for thread %d" % (index+1))
				t0 = time.time()
			mentions = r.get_inbox(limit=INBOX_LIMIT)
			for com in mentions:
				if int(com.name[3:], 36) % MONITOR_PROCESSES != index: 
					continue # One of the other monitor threads is handling this one; skip
				if com.name in started:
					continue # We've already started on this one, move on
				started.append(com.name)
				try:
					if com.subreddit == None:
						continue
					if com.subreddit.display_name in banned:
						log("%s: (%d) Ignored request from banned subreddit %s" % (com.name,index+1,com.subreddit.display_name))
						continue
				except praw.errors.Forbidden:
					continue
				res = re.search(req_pat, com.body.lower())
				if res == None:
					continue # We were mentioned but it's not a proper request, move on
				try:
					if USER.lower() in [rep.author.name.lower() for rep in com.replies if rep.author != None]:
						continue # We've already hit this one, move on
				except praw.errors.Forbidden:
					continue
				
				warnings.simplefilter("ignore")
				try:
					log("%s: processing" % (com.name), console_only=True)
					#mp.Process(target=process, args=(q, com, res.group(0), index+1)).start()
					process(q, com, res.group(0), index+1)
				except Exception:
					continue
				while q.qsize() > 0:
					item = q.get()
					if item == 'clear':
						log("Clearing list of started tasks")
						started = []
					elif item == 'quit':
						log("Stopping main process")
						return
					elif item in started:
						started.remove(item)

				time.sleep(1)
				
		except praw.errors.InvalidComment:
			continue # This one was completely trashing the console, so handle it silently.
		except AssertionError:
			r = get_r()
			continue
		# General-purpose catch to make the script unbreakable.
		except Exception as ex:
			log(str(index+1) + ": " + str(type(ex)) + ": " + str(ex))
			time.sleep(1)
			continue