Example #1
0
 def test_parent__submission(self):
     comment = Comment(self.reddit, "cklfmye")
     with self.recorder.use_cassette("TestComment.test_parent__submission"):
         parent = comment.parent()
         assert comment in parent.comments
     assert isinstance(parent, Submission)
     assert parent.fullname == comment.parent_id
Example #2
0
 def test_parent__submission(self):
     comment = Comment(self.reddit, 'cklfmye')
     with self.recorder.use_cassette('TestComment.test_parent__submission'):
         parent = comment.parent()
         assert comment in parent.comments
     assert isinstance(parent, Submission)
     assert parent.fullname == comment.parent_id
Example #3
0
def on_comment(comment: models.Comment):
    try:
        parent = comment.parent()
        if type(parent) is models.Comment:
            # Did an uninfected person reply to an infected persons comment?
            if parent.author_flair_text and "INFECTED" in parent.author_flair_text and (
                (comment.author_flair_text
                 and "INFECTED" not in comment.author_flair_text)
                    or not comment.author_flair_text):
                # infection!
                infect(comment, parent)
        else:  # if type(parent) is models.Submission
            # Did an uninfected person reply to an infected persons submission? Roll dice for a 1 in 100
            if parent.author_flair_text and "INFECTED" in parent.author_flair_text and (
                (comment.author_flair_text
                 and "INFECTED" not in comment.author_flair_text)
                    or not comment.author_flair_text) and random.randint(
                        1, 100) == 69:
                infect(comment, parent)
        # if _debug:
        #     print(comment)
        # TSV Format: Timestamp, Commentor Name, Commentor Comment ID, Commented on User, Commented on Item ID, Item Type, Commented on ?Infected? User
        _commentlog.write("{}\tu/{}\t{}\tu/{}\t{}\t{}\t{}\n".format(
            str(datetime.datetime.now()), comment.author.name, comment.id,
            "deleted" if not parent.author else parent.author.name, parent.id,
            "C" if type(parent) is models.Comment else "S", "I" if
            (parent.author_flair_text
             and "INFECTED" in parent.author_flair_text) else "N"))
    except Exception as ex:
        logger.info("ERROR IN ON_COMMENT")
        logger.info(str(ex))
        pass
Example #4
0
 def test_parent__comment(self):
     comment = Comment(self.reddit, "cklhv0f")
     with self.recorder.use_cassette("TestComment.test_parent__comment"):
         parent = comment.parent()
         parent.refresh()
         assert comment in parent.replies
     assert isinstance(parent, Comment)
     assert parent.fullname == comment.parent_id
Example #5
0
 def test_parent__comment(self):
     comment = Comment(self.reddit, 'cklhv0f')
     with self.recorder.use_cassette('TestComment.test_parent__comment'):
         parent = comment.parent()
         parent.refresh()
         assert comment in parent.replies
     assert isinstance(parent, Comment)
     assert parent.fullname == comment.parent_id
    def should_respond(self, comment: Comment) -> bool:
        if not isinstance(comment.parent(), Submission):
            return False
        if not re.findall(r'([A-Z]{1,2}[0-9]{4}\-?[A-Za-z0-9]*\:\ *\w+)', comment.body or ""):
            return False

        return comment.submission.link_flair_text in [
            submission_types.EK_STEMMING, submission_types.TK_STEMMING,
            submission_types.EK_TK_STEMMING
        ]
Example #7
0
def remove_post(reddit: Reddit, comment: Comment, message: str, mod_note: str,
                note_message: str, strike: bool):
    comment.parent().edit(message + f'\n\n{config["suffix"]}')
    comment.submission.mod.remove(spam=False, mod_note=mod_note)
    c.execute('DELETE FROM pendingposts WHERE submission_id=?',
              (comment.submission.id, ))
    conn.commit()

    # Time to update the usernotes...
    if strike:
        print("Updating usernotes...")
        usernotespage = reddit.subreddit(config['subreddit']).wiki["usernotes"]
        usernotescontent = json.loads(usernotespage.content_md)
        usernotes = decode_blob(usernotescontent['blob'])
        username = comment.submission.author.name

        mod_number = usernotescontent['constants']['users'].index(
            'Enslaved_Horny_AI')

        if username in usernotes:
            usernotes[username]['ns'].append({
                'l': f'l,{comment.submission.id}',
                'm': mod_number,
                'n': note_message,
                't': int(time.time()),
                'w': 0
            })
        else:
            usernotes[username] = {
                'ns': [{
                    'l': f'l,{comment.submission.id}',
                    'm': mod_number,
                    'n': note_message,
                    't': int(time.time()),
                    'w': 0
                }]
            }

        usernotescontent["blob"] = encode_blob(usernotes)
        usernotespage.edit(
            content=json.dumps(usernotescontent, separators=(',', ':')))
        print('User notes updated.')
Example #8
0
 def test_parent__chain(self):
     comment = Comment(self.reddit, "dkk4qjd")
     counter = 0
     with self.recorder.use_cassette("TestComment.test_parent__chain"):
         comment.refresh()
         parent = comment.parent()
         while parent != comment.submission:
             if counter % 9 == 0:
                 parent.refresh()
             counter += 1
             parent = parent.parent()
Example #9
0
 def test_parent__chain(self):
     comment = Comment(self.reddit, 'dkk4qjd')
     counter = 0
     with self.recorder.use_cassette('TestComment.test_parent__chain'):
         comment.refresh()
         parent = comment.parent()
         while parent != comment.submission:
             if counter % 9 == 0:
                 parent.refresh()
             counter += 1
             parent = parent.parent()
def parse_comment(comment: Comment) -> list():
    row = []
    row.append(comment.fullname) # Comment Id
    row.append(comment.author.name) # Author Username
    row.append(datetime.fromtimestamp(comment.created)) # Timestamp
    row.append(comment.subreddit.display_name) # Subreddit Name
    row.append(str(comment.parent().author)) # User author replied to

    # Sentiment Analysis
    sentiment = TextBlob(comment.body).sentiment
    row.append(sentiment.polarity) # Comment Polarity (Positive / Negative)
    row.append(sentiment.subjectivity) # Comment Subjectivity

    # Thread length: how many other replies were made to same comment?
    if isinstance(comment.parent(), Comment):
        if comment.parent().replies is not None:
            row.append(len(comment.parent().replies))
    elif isinstance(comment.parent(), Submission):
        row.append(len(comment.parent().comments))
    else:
        row.append(0) # Something unexpected happened
    
    # Debugging:
    print(f"Thread Length: {row[-1]}")

    return row
Example #11
0
def match_commands(comment: Comment, accents=True) -> set:
    """
    Return a set with tuples of the form ((reward, reward_images), recipient),
    one for each match in the body of the provided comment.
    """
    if accents:
        content = comment.body
    else:
        content = remove_accents(comment.body)

    return {(commands[m.group(1).lower()], m.group(2)
             or comment.parent().author.name)
            for m in PATTERN.finditer(content)}
Example #12
0
async def process_comment(comment: Comment, reddit: Reddit):
	# Mod override - if the user is a moderator, has "override" in his comment, and
	if not comment.is_root and comment.author.name in comment.subreddit.moderator() and "override" in comment.body:
		print("Moderator override activated.")

		# get rid of any override leftovers
		body = comment.body.replace('override', '').strip()

		url = extract_url(body)

		if not url:
			# no URL present, so we execute the british
			comment.reply("That doesn't seem to be a valid URL. Try again?"
			              f'\n\n{config["suffix"]}')
			return

		if 'nhentai.net' in url:

			nums_regex = re.compile(r"https://nhentai\.net/g/(\d+)/")
			nums_match = nums_regex.match(url)
			nums = nums_match.group(1)

			try:
				magazine, market, data = await nhentai_fetcher.check_link(url)
			except Exception:
				print("Invalid page.")
				comment.reply("That doesn't seem to be a valid nhentai page. Try again?"
				              f'\n\n{config["suffix"]}')
				return

			parodies = '' if len(data[3]) == 0 else f"**Parodies:**  \n{', '.join(data[3])}\n\n"
			characters = '' if len(data[4]) == 0 else f"**Characters:**  \n{', '.join(data[4])}\n\n"
			tags = '**Tags:**  \nNone\n\n' if len(data[2]) == 0 else f"**Tags:**  \n{', '.join(data[2])}\n\n"

			god_list = ""

			try:
				has_entry, entry = await wholesomelist_fetcher.process_nums(nums)
				if has_entry:
					print(entry)
					god_list = f"\\-\\-\\-\n\n[Wholesome Hentai God List #{entry['id']}](https://wholesomelist.com/list/{entry['uuid']})  \n" \
					           '\n' + (# f'**Tier: {entry["tier"]}**\n\n' + (
						           '' if (entry['note'] == 'None') else f'**Note:** {entry["note"]}  \n') + \
					           f'**Tags:** ' + ('None' if len(entry["tags"]) == 0 else entry['tags']) + "\n\n"
			except Exception:
				god_list = ""

			comment.parent().edit(
				f"The source OP provided:  \n> <{url}>\n\nAlt link: [cubari.moe](https://cubari.moe/read/nhentai/{nums}/1/1/)\n\n"
				f'**{markdown_escape(data[0])}**  \nby {data[1] if data[1] else "Unknown"}\n\n{data[5]} pages\n\n{parodies}{characters}{tags}{god_list}'
				f'{config["suffix"]}'
			)

		else:
			imgur = re.compile(r"https://imgur\.com/a/(.{5,7})/")
			imgur_match = imgur.match(url)

			if imgur_match:
				comment.parent().edit(
					f"The source OP provided:  \n> <{url}>\n\nAlt link: [cubari.moe](https://cubari.moe/read/imgur/{imgur_match.group(1)}/1/1/)\n\n"
					f'{config["suffix"]}'
				)
			else:
				comment.parent().edit(
					f"The source OP provided:  \n> <{url}>\n\n"
					f'{config["suffix"]}'
				)

		# The post is good.
		print('Updating database and cleaning up...')
		c.execute('DELETE FROM posts WHERE source=?', (url,))
		approve_post(reddit, comment, url)

		# Reapprove the post if it was removed
		if comment.submission.removed:
			print("This post was removed. Reapproving...")
			comment.submission.mod.approve()
		else:
			print("This post was not removed. Ignoring...")

	# If this is the reply to a sauce request, handle it
	elif not comment.is_root and c.execute('SELECT * FROM pendingposts WHERE submission_id=?', (comment.submission.id,)).fetchone():
		c.execute('SELECT * FROM pendingposts WHERE submission_id=?', (comment.submission.id,))
		submission_id, author, comment_id = c.fetchone()

		# Normal handling
		if comment_id == comment.parent_id[3:] and author == comment.author.name:
			# It's a reply to a sauce request.
			print("Sauce reply found.")
			print(comment.body)

			# If there is no applicable source...
			if comment.body.lower() == 'none':
				comment.parent().edit(
					'OP has indicated that there is no applicable source.'
					f'\n\n{config["suffix"]}'
				)
				c.execute('DELETE FROM pendingposts WHERE submission_id=?', (comment.submission.id,))
				conn.commit()

				comment.submission.mod.approve()
				return

			url = extract_url(comment.body)

			if not url:
				# no URL present, so we execute the british
				comment.reply("That doesn't seem to be a valid URL. Try again?"
				              f'\n\n{config["suffix"]}')
				return

			# Handle any licensed sites here
			for site in licensed_sites:
				if site in url:
					print("It's a licensed site.")
					remove_post(reddit, comment,
					    'The link you provided links to a site that solely rips licensed content. As such, it breaks rule 4.\n\n'
					    'Please read our [guide on how to spot licensed doujins](https://www.reddit.com/r/wholesomehentai/wiki/licensedguide)'
					    ' to avoid making this mistake in the future.',
					    'Licensed link',
					    'Rule 4 - Linked to hentai.cafe/hentainexus/hentaimimi',
					    True
					)

					return

			# Check if the post is a repost or not
			c.execute('SELECT * FROM commonreposts WHERE source=?', (url,))
			is_common_repost = c.fetchone()
			if is_common_repost:  # if this tuple even exists, it's uh oh stinky
				# It's a really common repost. Kill it.
				print('Common repost detected!')

				remove_post(reddit, comment,
					'The link you provided is a **very common repost** on this subreddit.\n\n'
					'Please read our [list of common reposts](https://www.reddit.com/r/wholesomehentai/wiki/posts), to avoid '
					'posting common reposts in the future.',
					'Really common repost.',
				    'Rule 10 - Common Repost',
					True
				)

				return

			# Check if the post is a repost that isn't that common
			c.execute('SELECT * FROM posts WHERE source=?', (url,))
			post = c.fetchone()
			if post:
				print('Post found in repost database.')
				# It's a repost.
				# Check how recently it was reposted (604800 seconds/week)
				if comment.submission.created_utc - post[2] > (12 * 604800):
					# It's already been enough since this was last posted.
					# Delete the entry, and we'll add it back later. (With the current timestamp)
					c.execute('DELETE FROM posts WHERE source=?', (url,))
					conn.commit()
					print('It\'s been long enough since this was last posted!')
				else:
					old_submission = reddit.submission(url=f'https://reddit.com{post[0]}')
					if (not old_submission.removed) and ((not (old_submission and old_submission.author)) or (old_submission.author.name == author)):
						# It's the same person. It's fine.
						print('OP is the same person. Ignoring...')
						c.execute('DELETE FROM posts WHERE source=?', (url,))
						conn.commit()
					else:
						if post[3] != 0:
							print('It\'s a recently removed repost. Removing...')

							remove_post(reddit, comment,
								f'The link you provided has already been [posted and removed](https://reddit.com{post[0]}) recently.\n\n'
								'Please check the previous post to see why it was removed. If you believe that the previous post was wrongly removed '
								f'or some other exception has occurred, please [contact the mods](https://www.reddit.com/message/compose?to=/r/{config["subreddit"]}).\n\n'
								'Otherwise, please make sure to [read the rules](https://reddit.com/r/wholesomehentai/wiki/rules) in the future.',
								'Removed repost.',
								'Reposting a removed post',
								True
							)

						else:
							# It's not been long enough since the last post. Link them to the last post and delete the entry.
							print('It\'s a recent repost. Removing...')

							remove_post(reddit, comment,
								f'The link you provided has [already been posted](https://reddit.com{post[0]}) recently.\n\n'
								'Please [check here](https://reddit.com/r/wholesomehentai/wiki/posts) before posting to avoid posting reposts in the future.',
								'Repost.',
						        'Rule 10 - Repost',
								True
							)

						return

			if 'nhentai.net' in url:
				# hoo boy
				print('nhentai URL detected, parsing info / magazines')

				if "nhentai.net/g/" not in url:
					comment.reply(f'That\'s not a valid nhentai page!\n\n{config["suffix"]}')
					return

				nums_regex = re.compile(r"https://nhentai\.net/g/(\d+)/")
				nums_match = nums_regex.match(url)
				nums = nums_match.group(1)

				for attempt in range(3):
					try:
						magazine, market, data = await nhentai_fetcher.check_link(url)
						break
					except Exception:
						if attempt == 2:
							print("Invalid page.")
							print(url)
							comment.reply("Either that isn't a valid nhentai page, or my connection to nhentai has a problem currently. Try again?" f'\n\n{config["suffix"]}')
							return
						else:
							await asyncio.sleep(1)

				if magazine:
					# It's licensed!
					print("Licensed magazine detected.")

					remove_post(reddit, comment,
						f'The provided source is licensed! It appears in the licensed magazine issue `{magazine}`.\n\n'
						f'Please [contact the mods](https://www.reddit.com/message/compose?to=/r/{config["subreddit"]}) if you think this is a mistake. Otherwise, please read the '
						'[guide on how to spot licensed doujins.](https://www.reddit.com/r/wholesomehentai/wiki/licensedguide)',
						f'Licensed, appears in magazine {magazine}',
					    f'Rule 4 - Licensed (appears in {magazine})',
						True
					)

					return

				if market:
					# It literally has 2d-market.com in the title.
					print("2d-market in title.")

					remove_post(reddit, comment,
						f'The provided source is licensed! It has `2d-market.com` in the title.\n\n'
						f'Please [contact the mods](https://www.reddit.com/message/compose?to=/r/{config["subreddit"]}) if you think this is a mistake. Otherwise, please read the '
						'[guide on how to spot licensed doujins.](https://www.reddit.com/r/wholesomehentai/wiki/licensedguide)',
						f'Licensed, has 2d-market.com in title',
					    f'Rule 4 - Licensed (2d-market.com in title)',
						True
					)

					return

				if "english" not in data[6]:
					print("The language of this doujin does not seem to be English.")
					remove_post(reddit, comment,
					    'The provided source does not seem to be in English.\n\n'
					    'This subreddit only allows English submissions, as most people cannot understand other languages.\n\n'
					    f'If you believe this was a mistake, you can [contact the mods](https://www.reddit.com/message/compose?to=/r/{config["subreddit"]}).',
					    'Not English',
					    'Rule 2 - Non-English Source',
					    False
					)

					return

				detected_artists = []
				for artist in licensed_artists:
					if artist in data[1].lower():
						detected_artists.append(artist)

				if len(detected_artists) != 0:
					# Oh no, there's an illegal artist!
					print("Illegal artists detected: " + ', '.join(detected_artists))

					remove_post(reddit, comment,
						f'The provided source has the following disallowed artists:\n```\n{", ".join(detected_artists)}\n```\n'
						'These artists are banned because their works are always or almost always licensed. '
						f'Please [contact the mods](https://www.reddit.com/message/compose?to=/r/{config["subreddit"]}) if you think this is '
						'an unlicensed exception. '
						'Otherwise, make sure you understand Rule 4.',
						f'Has the licensed artist(s): {", ".join(detected_artists)}',
					    f'Rule 4 - Has the artists {", ".join(detected_artists)}',
						True
					)

					return

				detected_tags = []
				for tag in data[2]:
					if tag in unwholesome_tags:
						detected_tags.append(tag)

				if len(detected_tags) != 0:
					# Oh no, there's an illegal tag!
					print("Illegal tags detected: " + ', '.join(detected_tags))

					remove_post(reddit, comment,
						f'The provided source has the following disallowed tags:\n```\n{", ".join(detected_tags)}\n```\n'
						'These tags are banned because they are either almost never wholesome or almost always licensed. '
						f'Please [contact the mods](https://www.reddit.com/message/compose?to=/r/{config["subreddit"]}) if you think this is either '
						'a mistagged doujin or a wholesome/unlicensed exception. '
						'Otherwise, make sure you understand Rules 1, 4, and 5.',
						f'Has the illegal tag(s): {", ".join(detected_tags)}',
					    f'Rule 1/4/5 - Has the tags {", ".join(detected_tags)}',
						True
					)

					return

				detected_characters = []
				for character in data[4]:
					if character in underage_characters:
						cur_list = underage_characters[character]
						parodies = data[3]

						for parody in parodies:
							for item in cur_list:
								series_list = item['series']
								for series in series_list:
									if series.lower().strip() == parody:
										detected_characters.append([character, series, item['age'], item['note']])

				if len(detected_characters) != 0:
					# Oh no, there's an illegal character!
					chars_list = []
					for character in detected_characters:
						chars_list.append(character[0])

					chars_str = ', '.join(chars_list)
					print("Illegal characters detected: " + chars_str)

					remove_post(reddit, comment,
						f'The provided source has the following disallowed characters:\n\n{generate_character_string(detected_characters)}\n'
						'These characters are banned because they are underage.\n\n'
						f'If you believe one of these characters is actually 18+ (because either the Note exception applies, or the mod team made a mistake), please [contact the mods](https://www.reddit.com/message/compose?to=/r/{config["subreddit"]}). '
						'Otherwise, make sure you understand Rule 1, and have checked our [spreadsheet of underage characters.](https://docs.google.com/spreadsheets/d/1rnTIzml80kQJPlNCQzluuKHK8Dzejk2Xg7J4YYN4FaM/)',
						f'Has the underage char(s): {chars_str}',
					    f'Rule 1 - Has the chars {chars_str}',
						True
					)

					return

				parodies = '' if len(data[3]) == 0 else f"**Parodies:**  \n{', '.join(data[3])}\n\n"
				characters = '' if len(data[4]) == 0 else f"**Characters:**  \n{', '.join(data[4])}\n\n"
				tags = '**Tags:**  \nNone\n\n' if len(data[2]) == 0 else f"**Tags:**  \n{', '.join(data[2])}\n\n"

				god_list = ""

				try:
					has_entry, entry = await wholesomelist_fetcher.process_nums(nums)
					if has_entry:
						print(entry)
						god_list = f"\\-\\-\\-\n\n[Wholesome Hentai God List #{entry['id']}](https://wholesomelist.com/list/{entry['uuid']})  \n" \
						           '\n' + ( # f'**Tier: {entry["tier"]}**\n\n' + (
							           '' if (entry['note'] == 'None') else f'**Note:** {entry["note"]}  \n') + \
						           f'**Tags:** ' + ('None' if len(entry["tags"]) == 0 else entry['tags']) + "\n\n"
				except Exception:
					god_list = ""

				comment.parent().edit(
					f"The source OP provided:  \n> <{url}>\n\nAlt link: [cubari.moe](https://cubari.moe/read/nhentai/{nums}/1/1/)\n\n"
					f'**{markdown_escape(data[0])}**  \nby {data[1] if data[1] else "Unknown"}\n\n{data[5]} pages\n\n{parodies}{characters}{tags}{god_list}'
					f'{config["suffix"]}'
				)

			else:
				imgur = re.compile(r"https://imgur\.com/a/(.{5,7})/")
				imgur_match = imgur.match(url)

				if imgur_match:
					comment.parent().edit(
						f"The source OP provided:  \n> <{url}>\n\nAlt link: [cubari.moe](https://cubari.moe/read/imgur/{imgur_match.group(1)}/1/1/)\n\n"
						f'{config["suffix"]}'
					)
				else:
					comment.parent().edit(
						f"The source OP provided:  \n> <{url}>\n\n"
						f'{config["suffix"]}'
					)

			# If we made it here, the post is good. Clean up any trackers and add a post entry to the database.
			print('Updating database and cleaning up...')
			approve_post(reddit, comment, url)