def nudity_blur(image): detector = NudeDetector() classes = [ 'EXPOSED_ANUS', 'EXPOSED_BUTTOCKS', 'COVERED_BREAST_F', 'EXPOSED_BREAST_F', 'EXPOSED_GENITALIA_F', 'EXPOSED_GENITALIA_M', 'EXPOSED_BUTTOCKS', 'EXPOSED_BREAST_F', 'EXPOSED_GENITALIA_F', 'EXPOSED_GENITALIA_M', 'EXPOSED_BREAST_M', 'COVERED_GENITALIA_F', 'COVERED_BREAST_F' ] for i in detector.detect(image): if i['label'] in classes: # if i['label'] in [] x, y, w, h = i['box'] Img = cv2.medianBlur(image[y:h, x:w], ksize=41) image[y:h, x:w] = Img return image
def ImageDescribing(tSourceImage, tDetector='', CENSORING_LABELS=[ "EXPOSED_BREAST_F", "EXPOSED_GENITALIA_F", "EXPOSED_GENITALIA_M" ]): """ tSourceImage: Path, or BytesIO Object tDetector: NudeNet.Detector. If not provided, one will be created. """ if not tDetector: tDetector = NudeDetector() tDescription = tDetector.detect(tSourceImage) return [ tDetail for tDetail in tDescription if tDetail['label'] in CENSORING_LABELS ]
'filename', 'file_size', 'file_attributes', 'region_count', 'region_id', 'region_shape_attributes', 'region_attributes' ]) #CSV for f in files: try: while True: print("Working on " + f) img_C = Image.open(f).convert("RGB") x, y = img_C.size img_C = np.array(img_C) image = img_C[:, :, ::-1].copy() img_rgb = img_C[:, :, ::-1].copy() color = rand_color() detection = detector.detect(f) label = ['F_GENITALIA', 'M_GENITALIA'] # all_regions = [ i['box'] for i in detection if i['label'] in label ] # if all_regions == []: # skip entire detection, avoid saving #os.remove(f, ) #to remove file from input os.rename(f, f.replace( rootdir, rejected, 1)) #to remove file from input to rejected print('skipping image with failed nudenet detection') break print(all_regions) # interp = random.choices(
from nudenet import NudeClassifier from nudenet import NudeDetector from tqdm import tqdm from shutil import copyfile # classifier = NudeClassifier('models/classifier_model') detector = NudeDetector('models/detector_model') # print(classifier.classify( # 'splitted/_momoiroiro_Cute_or_sexy__😆_c4h2ar_2.jpg')) def is_naked(features): naked_label = ['F_BREAST', 'F_GENITALIA', 'M_GENITALIA', 'M_BREAST'] for feature in features: if feature['label'] in naked_label: return True return False files = os.listdir('splitted') for filename in tqdm(files): path = os.path.join('splitted', filename) out_dir = None if is_naked(detector.detect(path)): out_dir = 'naked' else: out_dir = 'not_naked' out_path = os.path.join(out_dir, filename) copyfile(path, out_path)
class Detections(commands.Cog): def __init__(self, bot: rainbot) -> None: self.bot = bot self.spam_detection: DefaultDict[str, List[int]] = defaultdict(list) self.repetitive_message: DefaultDict[str, Counter] = defaultdict(Counter) self.INVITE_REGEX = re.compile( r'((http(s|):\/\/|)(discord)(\.(gg|io|me)\/|app\.com\/invite\/)([0-z]+))' ) self.ENGLISH_REGEX = re.compile( r'(?:\(╯°□°\)╯︵ ┻━┻)|[ -~]|(?:' + UNICODE_EMOJI + r')|(?:\U00002018|\U00002019|\s)|[.!?\\\-\(\)]|ツ|¯|(?:┬─┬ ノ\( ゜-゜ノ\))' ) # U2018 and U2019 are iOS quotes self.nude_detector = NudeDetector() self.nude_image_cache: LFUCache[str, List[str]] = LFUCache(50) self.detections = [] for func in self.__class__.__dict__.values(): if isinstance(func, Detection): self.detections.append(func) @Cog.listener() async def on_message(self, m: MessageWrapper) -> None: if self.bot.dev_mode: if m.guild and m.guild.id != 733697261065994320: return if (self.bot.dev_mode and (m.guild and m.guild.id != 733697261065994320) ) or m.type != discord.MessageType.default: return for func in self.detections: await func.trigger(self, m) @detection('sexually_explicit', require_attachment=True) async def sexually_explicit(self, m: MessageWrapper) -> None: for i in m.attachments: if i.filename.endswith('.png') or i.filename.endswith( '.jpg') or i.filename.endswith('.jpeg'): with NamedTemporaryFile(mode='wb+', delete=False) as fp: async with self.bot.session.get(i.url) as resp: fp.write(await resp.read()) await self.bot.loop.run_in_executor( None, functools.partial(self.get_nudenet_classifications, m, fp.name)) @detection('mention_limit') async def mention_limit(self, m: MessageWrapper) -> None: mentions = [] for i in m.mentions: if i not in mentions and i != m.author and not i.bot: mentions.append(i) guild_config = await self.bot.db.get_guild_config(m.guild.id) if len(mentions) >= guild_config.detections.mention_limit: await m.detection.punish( self.bot, m, reason=f'Mass mentions ({len(m.mentions)})') @detection('max_lines') async def max_lines(self, m: MessageWrapper) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) if len(m.content.splitlines()) > guild_config.detections.max_lines: await m.detection.punish(self.bot, m) @detection('max_words') async def max_words(self, m: MessageWrapper) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) if len(m.content.split(' ')) > guild_config.detections.max_words: await m.detection.punish(self.bot, m) @detection('max_characters') async def max_characters(self, m: MessageWrapper) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) if len(m.content) > guild_config.detections.max_characters: await m.detection.punish(self.bot, m) @detection('filters') async def filtered_words(self, m: MessageWrapper) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) words = [ i for i in guild_config.detections.filters if i in m.content.lower() ] if words: await m.detection.punish( self.bot, m, reason=f'Sent a filtered word: {words[0]}') @detection('regex_filters') async def regex_filter(self, m: MessageWrapper) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) matches = [ i for i in guild_config.detections.regex_filters if re.search(i, m.content) ] if matches: await m.detection.punish(self.bot, m, reason='Sent a filtered message.') @detection('image_filters', require_attachment=True) async def image_filters(self, m: MessageWrapper) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) for i in m.attachments: stream = io.BytesIO() await i.save(stream) try: img = Image.open(stream) except UnidentifiedImageError: pass else: image_hash = str(average_hash(img)) img.close() if image_hash in guild_config.detections.image_filters: await m.detection.punish(self.bot, m, reason='Sent a filtered image') break @detection('block_invite') async def block_invite(self, m: MessageWrapper) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) invite_match = self.INVITE_REGEX.findall(m.content) if invite_match: for i in invite_match: try: invite = await self.bot.fetch_invite(i[-1]) except discord.NotFound: pass else: if not (invite.guild.id == m.guild.id or str(invite.guild.id) in guild_config.whitelisted_guilds): await m.detection.punish( self.bot, m, reason= f'Advertising discord server `{invite.guild.name}` (<{invite.url}>)' ) @detection('english_only') async def english_only(self, m: MessageWrapper) -> None: english_text = ''.join(self.ENGLISH_REGEX.findall(m.content)) if english_text != m.content: await m.detection.punish(self.bot, m) @detection('spam_detection') async def spam_detection(self, m: MessageWrapper) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) limit = guild_config.detections.spam_detection if len(self.spam_detection.get(str(m.author.id), [])) >= limit: reason = f'Exceeding spam detection ({limit} messages/5s)' await m.detection.punish(self.bot, m, reason=reason, purge_limit=len(self.spam_detection[str( m.author.id)])) try: del self.spam_detection[str(m.author.id)] except KeyError: pass else: self.spam_detection[str(m.author.id)].append(m.id) await asyncio.sleep(5) try: self.spam_detection[str(m.author.id)].remove(m.id) if not self.spam_detection[str(m.author.id)]: del self.spam_detection[str(m.author.id)] except ValueError: pass @detection('repetitive_message') async def repetitive_message(self, m: MessageWrapper) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) limit = guild_config.detections.repetitive_message if self.get_most_common_count_repmessage(m.author.id) >= limit: reason = f'Repetitive message detection ({limit} identical messages/1m)' await m.detection.punish( self.bot, m, reason=reason, purge_limit=self.get_most_common_count_repmessage(m.author.id)) try: del self.repetitive_message[str(m.author.id)] except KeyError: pass else: self.repetitive_message[str(m.author.id)][m.content] += 1 await asyncio.sleep(60) try: self.repetitive_message[str(m.author.id)][m.content] -= 1 if not self.repetitive_message[str(m.author.id)].values(): del self.repetitive_message[str(m.author.id)] except KeyError: pass @detection('repetitive_characters') async def repetitive_characters(self, m: MessageWrapper) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) limit = guild_config.detections.repetitive_characters counter = Counter(m.content) for c, n in counter.most_common(None): if n > limit: reason = f'Repetitive character detection ({n} > {limit} of {c} in message)' await m.detection.punish(self.bot, m, reason=reason) break @detection('caps_message', check_enabled=False) async def caps_message(self, m: MessageWrapper) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) percent = guild_config.detections.caps_message_percent min_words = guild_config.detections.caps_message_min_words if all((percent, min_words)): # this is the check enabled english_text = ''.join(self.ENGLISH_REGEX.findall(m.content)) if english_text and len(m.content.split(' ')) >= min_words and ( len([i for i in english_text if i.upper() == i]) / len(english_text)) >= percent: await m.detection.punish(self.bot, m) def get_most_common_count_repmessage(self, id_: int) -> int: most_common = self.repetitive_message.get(str(id_), Counter()).most_common(1) if most_common: if most_common[0]: return most_common[0][1] return 0 def get_nudenet_classifications(self, m, path) -> None: try: img = Image.open(path) except UnidentifiedImageError: os.remove(path) return image_hash = str(average_hash(img)) img.close() try: labels = self.nude_image_cache[image_hash] except KeyError: result = self.nude_detector.detect(path, min_prob=0.8) labels = [] for i in result: labels.append(i['label']) os.remove(path) if labels: self.nude_image_cache[image_hash] = labels self.bot.loop.create_task(self.nudenet_callback(m, labels)) async def nudenet_callback(self, m, labels) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) for i in guild_config.detections.sexually_explicit: if i in labels: await m.detection.punish( self.bot, m, reason=f'Explicit image detection {tuple(labels)}') break
import json import os import tensorflow as tf os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' import tensorflow as tf import warnings warnings.filterwarnings("ignore") #tf.logging.set_verbosity(tf.logging.ERROR) tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR) #img_path = 'output/frames/BEBE.mkv/frame0034.jpg' img_path = 'output/frames/test/test.jpg' detector = NudeDetector('models/detector_model') result = detector.detect(img_path, min_prob=0.48) ## [{'box': [352, 688, 550, 858], 'score': 0.9603578, 'label': 'BELLY'}, {'box': [507, 896, 586, 1055], 'score': 0.94103414, 'label': 'F_GENITALIA'}, {'box': [221, 467, 552, 650], 'score': 0.8011624, 'label': 'F_BREAST'}, {'box': [359, 464, 543, 626], 'score': 0.6324697, 'label': 'F_BREAST'}] #[{'box': [204, 260, 362, 360], 'score': 0.6535794, 'label': 'BELLY'}, {'box': [190, 160, 360, 267], 'score': 0.5245675, 'label': 'F_BREAST'}, {'box': [162, 264, 233, 327], 'score': 0.3220556, 'label': 'F_BREAST'}] cv_image = cv2.imread(img_path) #json_result = json.loads() #print(json_result) #print(result) print("") print("") print("--------------------------------------------") for item in result: left = item['box'][0]
import os import json import tensorflow as tf tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR) from nudenet import NudeDetector detector = NudeDetector() # Performing detection result = detector.detect('/nsfw/one.jpg') result2 = detector.detect('/nsfw/two.xjpg') print('') print('') print('TEST RESULTS:') print('********************************************') print('') print('one.jpg') print(result) print('') print('two.jpg') print(result2) print('') print('********************************************') print('')
def filter(fr, scenes, removal): video = fr.src_video fileext = os.path.splitext(os.path.basename(video.url))[1] src_name = str(uuid.uuid4()) + '_' + str(current_millis()) src_path = os.path.join(settings.MEDIA_ROOT, src_name + fileext) print('##### start download %s' % src_path) client = storage.Client.from_service_account_json(settings.GCP_KEY_PATH) bucket = client.get_bucket(settings.BUCKET_NAME) blob = Blob(gcp_path(video.url), bucket) blob.download_to_filename(src_path) print('##### complete download %s' % src_path) video = cv2.VideoCapture(src_path) fps = video.get(cv2.CAP_PROP_FPS) num_frames = video.get(cv2.CAP_PROP_FRAME_COUNT) duration = int((num_frames / fps) * 1000) out_name = str(uuid.uuid4()) + '_' + str(current_millis()) out_path = os.path.join(settings.MEDIA_ROOT, out_name + fileext) infile = ffmpeg.input(src_path) if removal: print('##### start removing %d scenes' % len(scenes)) start_times = sorted( [scene['start_millis'] / 1000 for scene in scenes]) end_times = sorted([scene['end_millis'] / 1000 for scene in scenes]) times_length = len(start_times) times = [] print(start_times, end_times) for idx in range(times_length): print(start_times[idx], end_times[idx]) if idx == 0: if start_times[idx] != 0: times.append((0, start_times[idx])) if idx == times_length - 1: times.append((end_times[idx], None)) if 0 < idx and times_length > 1: times.append((end_times[idx - 1], start_times[idx])) trims = [] print(times) for time in times: start = time[0] end = time[1] if end is None: trims.append(infile.trim(start=start).setpts('N/FR/TB')) else: trims.append( infile.trim(start=start, end=end).setpts('N/FR/TB')) print(trims) ffmpeg.concat(*trims).output(out_path).run(overwrite_output=True) else: # extract frames for detecting print('##### start extracting frames for detecting blurbox') detector = NudeDetector(settings.NUDE_NET_DETECTOR_MODEL_PATH) frames_dir = os.path.join(settings.MEDIA_ROOT, src_name) if not os.path.exists(frames_dir): os.makedirs(frames_dir) try: interval = 250 for scene in scenes: cur_millis = scene['start_millis'] while (True): video.set(cv2.CAP_PROP_POS_MSEC, cur_millis) ret, frame = video.read() if ret: frame_path = os.path.join(frames_dir, str(cur_millis) + '.jpg') cv2.imwrite(frame_path, frame) else: break cur_millis += interval if cur_millis >= scene[ 'end_millis'] or cur_millis > duration: break print('##### complete extracting frames for detecting blurbox') print('##### start detecting blurbox %s' % frames_dir) bps = BlurPointSet() for frame in sorted(os.listdir(frames_dir), key=lambda f: int(os.path.splitext(f)[0])): censors = detector.detect(os.path.join(frames_dir, frame)) print('detected blur box point %d from %s' % (len(censors), frame)) start_millis = int(os.path.splitext(frame)[0]) end_millis = start_millis + interval bps.add_censors(censors, start_millis, end_millis) print('##### complete detecting blurbox') print('##### start blur') blur_op = infile for overlay in bps.list_for_overlay(): blur_op = blur_op.overlay(infile.crop( x=overlay['x'], y=overlay['y'], width=overlay['width'], height=overlay['height']).filter_('boxblur', luma_radius=10, luma_power=10), x=overlay['x'], y=overlay['y'], enable=overlay['enable']) blur_op.output(out_path).run(overwrite_output=True) print('##### complete blur') shutil.rmtree(frames_dir) os.remove(src_path) except Exception as e: print('##### detect and blur failed %s', str(e)) os.remove(src_path) shutil.rmtree(frames_dir) raise e video.release() cv2.destroyAllWindows() return out_path
class Detections(commands.Cog): def __init__(self, bot): self.bot = bot self.spam_detection = defaultdict(list) self.repetitive_message = defaultdict(Counter) self.INVITE_REGEX = re.compile( r'((http(s|):\/\/|)(discord)(\.(gg|io|me)\/|app\.com\/invite\/)([0-z]+))' ) self.ENGLISH_REGEX = re.compile( r'[ -~]|(?:' + UNICODE_EMOJI + r')|(?:\U00002018|\U00002019|\s)|[.!?\\\-\(\)]|ツ|(?:\(╯°□°\)╯︵ ┻━┻)|(?:┬─┬ ノ\( ゜-゜ノ\))' ) # U2018 and U2019 are iOS quotes self.nude_detector = NudeDetector() self.nude_graph = tf.get_default_graph() self.nude_image_cache = LFUCache(50) @Cog.listener() async def on_message(self, m): if not m.guild or m.type != discord.MessageType.default or m.author.bot or self.bot.dev_mode: return guild_config = await self.bot.db.get_guild_config(m.guild.id) if get_perm_level(m.author, guild_config)[0] >= 5: return detection_config = guild_config.detections ignored_channels = guild_config.ignored_channels filtered_words = [ i for i in detection_config.filters if i in m.content.lower() ] invite_match = self.INVITE_REGEX.findall(m.content) english_text = ''.join(self.ENGLISH_REGEX.findall(m.content)) mentions = [] for i in m.mentions: if i not in mentions and i != m.author and not i.bot: mentions.append(i) warn_cmd = self.bot.get_command('warn add') ctx = await self.bot.get_context(m) ctx.author = m.guild.me ctx.command = warn_cmd # images if guild_config.detections.sexually_explicit: for i in m.attachments: if i.filename.endswith('.png') or i.filename.endswith( '.jpg') or i.filename.endswith('.jpeg'): with NamedTemporaryFile(mode='wb+', delete=False) as fp: async with self.bot.session.get(i.url) as resp: fp.write(await resp.read()) await self.bot.loop.run_in_executor( None, functools.partial(self.get_nudenet_classifications, m, fp.name)) if detection_config.mention_limit and len( mentions) >= detection_config.mention_limit and str( m.channel.id) not in ignored_channels.mention_limit: await m.delete() await ctx.invoke(warn_cmd, m.author, reason=f'Mass mentions ({len(m.mentions)})') await self.bot.mute(m.author, timedelta(minutes=10), reason=f'Mass mentions ({len(m.mentions)})') elif len(filtered_words) != 0 and str( m.channel.id) not in ignored_channels.filter: await m.delete() elif detection_config.block_invite and invite_match and str( m.channel.id) not in ignored_channels.block_invite: for i in invite_match: try: invite = await self.bot.fetch_invite(i[-1]) except discord.NotFound: pass else: if not (invite.guild.id == m.guild.id or str(invite.guild.id) in guild_config.whitelisted_guilds): await m.delete() await ctx.invoke( warn_cmd, m.author, reason= f'Advertising discord server (<{invite.url}>)') await self.bot.mute( m.author, timedelta(minutes=10), reason= f'Advertising discord server (<{invite.url}>)') elif detection_config.english_only and english_text != m.content and str( m.channel.id) not in ignored_channels.english_only: await m.delete() elif detection_config.spam_detection and len( self.spam_detection.get( str(m.author.id), [])) >= detection_config.spam_detection and str( m.channel.id) not in ignored_channels.spam_detection: await ctx.invoke( warn_cmd, m.author, reason= f'Exceeding spam detection ({detection_config.spam_detection} messages/5s)' ) await self.bot.mute( m.author, timedelta(minutes=10), reason= f'Exceeding spam detection ({detection_config.spam_detection} messages/5s)' ) await m.delete() for i in self.spam_detection[str(m.author.id)]: try: msg = await m.channel.fetch_message(i) await msg.delete() except discord.NotFound: pass elif detection_config.repetitive_message and self.get_most_common_count( m.author.id) >= detection_config.repetitive_message and str( m.channel.id) not in ignored_channels.repetitive_message: await ctx.invoke( warn_cmd, m.author, reason= f'Repetitive message detection ({detection_config.repetitive_message} identical messages/1m)' ) await ctx.invoke(self.bot.get_command('purge'), limit=self.get_most_common_count(m.author.id), member=m.author) await self.bot.mute( m.author, timedelta(minutes=10), reason= f'Repetitive message detection ({detection_config.repetitive_message} identical messages/1m)' ) if str(m.channel.id) not in ignored_channels.spam_detection: self.spam_detection[str(m.author.id)].append(m.id) await asyncio.sleep(5) self.spam_detection[str(m.author.id)].remove(m.id) if not self.spam_detection[str(m.author.id)]: del self.spam_detection[str(m.author.id)] if str(m.channel.id) not in ignored_channels.repetitive_message: self.repetitive_message[str(m.author.id)][m.content] += 1 await asyncio.sleep(60) self.repetitive_message[str(m.author.id)][m.content] -= 1 if not self.repetitive_message[str(m.author.id)].values(): del self.repetitive_message[str(m.author.id)] def get_most_common_count(self, id): most_common = self.repetitive_message.get(str(id), Counter()).most_common(1) if most_common: if most_common[0]: return most_common[0][1] return 0 def get_nudenet_classifications(self, m, path): img = Image.open(path) image_hash = str(average_hash(img)) img.close() try: labels = self.nude_image_cache[image_hash] except KeyError: with self.nude_graph.as_default(): result = self.nude_detector.detect(path) labels = [] for i in result: labels.append(i['label']) os.remove(path) if labels: self.nude_image_cache[image_hash] = labels self.bot.loop.create_task(self.nudenet_callback(m, labels)) async def nudenet_callback(self, m, labels): guild_config = await self.bot.db.get_guild_config(m.guild.id) for i in guild_config.detections.sexually_explicit: if i in labels: await m.delete() await self.bot.mute( m.author, timedelta(minutes=10), reason=f'Explicit image detection {tuple(labels)}') break
class Detections(commands.Cog): def __init__(self, bot: rainbot) -> None: self.bot = bot self.spam_detection: DefaultDict[str, List[int]] = defaultdict(list) self.repetitive_message: DefaultDict[str, Counter] = defaultdict(Counter) self.INVITE_REGEX = re.compile(r'((http(s|):\/\/|)(discord)(\.(gg|io|me)\/|app\.com\/invite\/)([0-z]+))') self.ENGLISH_REGEX = re.compile(r'[ -~]|(?:' + UNICODE_EMOJI + r')|(?:\U00002018|\U00002019|\s)|[.!?\\\-\(\)]|ツ|(?:\(╯°□°\)╯︵ ┻━┻)|(?:┬─┬ ノ\( ゜-゜ノ\))') # U2018 and U2019 are iOS quotes self.nude_detector = NudeDetector() self.nude_graph = tf.get_default_graph() self.nude_image_cache: LFUCache[str, List[str]] = LFUCache(50) self.detections = [] for func in self.__class__.__dict__.values(): if isinstance(func, Detection): self.detections.append(func) @Cog.listener() async def on_message(self, m: discord.Message) -> None: if self.bot.dev_mode: if m.guild.id != 733697261065994320: return if (self.bot.dev_mode and (m.guild and m.guild.id != 733697261065994320)) or m.type != discord.MessageType.default: return for func in self.detections: await func.trigger(self, m) @detection('auto_purge_trickocord', require_user=755580145078632508, allow_bot=True) async def auto_purge_trickocord(self, m: discord.Message) -> None: print(self, m) if m.embeds and m.embeds[0].title == 'A trick-or-treater has stopped by!': await asyncio.sleep(90) await m.delete() @detection('sexually_explicit', require_attachment=True) async def sexually_explicit(self, m: discord.Message) -> None: for i in m.attachments: if i.filename.endswith('.png') or i.filename.endswith('.jpg') or i.filename.endswith('.jpeg'): with NamedTemporaryFile(mode='wb+', delete=False) as fp: async with self.bot.session.get(i.url) as resp: fp.write(await resp.read()) await self.bot.loop.run_in_executor(None, functools.partial(self.get_nudenet_classifications, m, fp.name)) @detection('mention_limit') async def mention_limit(self, m: discord.Message) -> None: mentions = [] for i in m.mentions: if i not in mentions and i != m.author and not i.bot: mentions.append(i) guild_config = await self.bot.db.get_guild_config(m.guild.id) if len(mentions) >= guild_config.detections.mention_limit: await m.delete() await self.invoke('warn add', m, member=m.author, reason=f'Mass mentions ({len(m.mentions)})') await self.bot.mute(m.author, timedelta(minutes=10), reason=f'Mass mentions ({len(m.mentions)})') @detection('max_lines') async def max_lines(self, m: discord.Message) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) if len(m.content.splitlines()) > guild_config.detections.max_lines: await m.delete() return True @detection('max_words') async def max_words(self, m: discord.Message) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) if len(m.content.split(' ')) > guild_config.detections.max_words: await m.delete() return True @detection('max_characters') async def max_characters(self, m: discord.Message) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) if len(m.content) > guild_config.detections.max_characters: await m.delete() return True @detection('filter', check_enabled=False) async def filtered_words(self, m: discord.Message) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) words = [i for i in guild_config.detections.filters if i in m.content.lower()] if words: await m.delete() return True @detection('regex_filter', check_enabled=False) async def regex_filter(self, m: discord.Message) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) matches = [i for i in guild_config.detections.regex_filters if re.match(i, m.content)] if matches: await m.delete() return True @detection('block_invite') async def block_invite(self, m: discord.Message) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) invite_match = self.INVITE_REGEX.findall(m.content) if invite_match: for i in invite_match: try: invite = await self.bot.fetch_invite(i[-1]) except discord.NotFound: pass else: if not (invite.guild.id == m.guild.id or str(invite.guild.id) in guild_config.whitelisted_guilds): await m.delete() await self.invoke('warn add', m, member=m.author, reason=f'Advertising discord server {invite.guild.name} (<{invite.url}>)') await self.bot.mute(m.author, timedelta(minutes=10), reason=f'Advertising discord server {invite.guild.name} (<{invite.url}>)') @detection('english_only') async def english_only(self, m: discord.Message) -> None: english_text = ''.join(self.ENGLISH_REGEX.findall(m.content)) if english_text != m.content: await m.delete() @detection('spam_detection') async def spam_detection(self, m: discord.Message) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) limit = guild_config.detections.spam_detection if len(self.spam_detection.get(str(m.author.id), [])) >= limit: reason = f'Exceeding spam detection ({limit} messages/5s)' await self.bot.mute(m.author, timedelta(minutes=10), reason=reason) await self.invoke('warn add', m, member=m.author, reason=reason) await self.invoke('purge', m, member=m.author, limit=len(self.spam_detection[str(m.author.id)])) try: del self.spam_detection[str(m.author.id)] except KeyError: pass else: self.spam_detection[str(m.author.id)].append(m.id) await asyncio.sleep(5) try: self.spam_detection[str(m.author.id)].remove(m.id) if not self.spam_detection[str(m.author.id)]: del self.spam_detection[str(m.author.id)] except ValueError: pass @detection('repetitive_message') async def repetitive_message(self, m: discord.Message) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) limit = guild_config.detections.repetitive_message if self.get_most_common_count_repmessage(m.author.id) >= limit: reason = f'Repetitive message detection ({limit} identical messages/1m)' await self.bot.mute(m.author, timedelta(minutes=10), reason=reason) await self.invoke('warn add', m, member=m.author, reason=reason) await self.invoke('purge', m, member=m.author, limit=self.get_most_common_count_repmessage(m.author.id)) try: del self.repetitive_message[str(m.author.id)] except KeyError: pass else: self.repetitive_message[str(m.author.id)][m.content] += 1 await asyncio.sleep(60) try: self.repetitive_message[str(m.author.id)][m.content] -= 1 if not self.repetitive_message[str(m.author.id)].values(): del self.repetitive_message[str(m.author.id)] except KeyError: pass async def invoke(self, command, message: discord.Message, **kwargs) -> None: ctx = await self.bot.get_context(message) ctx.author = message.guild.me await ctx.invoke(self.bot.get_command(command), **kwargs) def get_most_common_count_repmessage(self, id_: int) -> int: most_common = self.repetitive_message.get(str(id_), Counter()).most_common(1) if most_common: if most_common[0]: return most_common[0][1] return 0 def get_nudenet_classifications(self, m, path) -> None: img = Image.open(path) image_hash = str(average_hash(img)) img.close() try: labels = self.nude_image_cache[image_hash] except KeyError: with self.nude_graph.as_default(): result = self.nude_detector.detect(path, min_prob=0.8) labels = [] for i in result: labels.append(i['label']) os.remove(path) if labels: self.nude_image_cache[image_hash] = labels self.bot.loop.create_task(self.nudenet_callback(m, labels)) async def nudenet_callback(self, m, labels) -> None: guild_config = await self.bot.db.get_guild_config(m.guild.id) for i in guild_config.detections.sexually_explicit: if i in labels: await m.delete() await self.bot.mute(m.author, timedelta(minutes=10), reason=f'Explicit image detection {tuple(labels)}') break
# Import module from nudenet import NudeDetector # initialize detector (downloads the checkpoint file automatically the first time) detector = NudeDetector() # detector = NudeDetector('base') for the "base" version of detector. dic = detector.detect('test.jpg') score = 0 count = 0 for part in dic: if part['score'] < 0.6: print(part['label'], "P**n") break else: print(part['label'], ':', part['score'])