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 __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)
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)
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 ]
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
def __init__(self, mode, specific_formats=None, specific_folder=None): self.mode = mode self.lst_of = {} self.doc_ext = [] self.img_ext = [] self.vid_ext = [] self.sound_ext = [] self.zip_ext = [] self.code_ext = [] self.media_ext = [] self.data_ext = [] self.app_ext = [] self.font_ext = [] self.sys_ext = [] self.flags = [] self.specifics = [] self.all_files = {} self.errors = [] self.file_structure = {} self.load_ext() self.now = datetime.now() self.dt_string = self.now.strftime("%d-%m-%Y %Hh%M") self.nude_classifier = NudeClassifier() self.nude_detector = NudeDetector() self.s = sched.scheduler(time.time, time.sleep) self.number_of_files = 0 self.time_taken = 0 self.prev_dir = None self.curr_dir = None self.faces = None self.points = None self.walked_dir = "checked.dir" self.all_walked = [] self.load_walked() self.available_dirs = [] self.non_available_dirs = [] self.attach = ":/" self.let_dir = [ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" ] self.runt = threading.Thread(target=self.find_all_dirs) self.runt.start() self.master_ext = [ self.doc_ext, self.img_ext, self.vid_ext, self.sound_ext, self.zip_ext, self.code_ext, self.media_ext, self.data_ext, self.app_ext, self.font_ext, self.sys_ext, self.flags ] self.type_s = [ "Documents", "Images", "Videos", "Sounds", "Compressed_Files", "Programming_Files", "Discs_Media", "Databases", "Applications", "Fonts", "System_Files", "Infected" ] self.face_detection = fc.Detection() self.face_recognition = fc.Recognition() self.face_verification = fc.Verification() if specific_formats is not None and specific_folder is not None: self.specifics = self.specifics + specific_formats self.master_ext.append(self.specifics) self.type_s.append(specific_folder)
# bot config bot_mode = config['bot']['mode'] debug = config.getboolean('bot', 'debug') token = config['bot']['token'] clientid = config['bot']['clientid'] prefix = str(config['bot']['prefix']) botperms = config['bot']['botperms'] # policy denythreshold = config.getfloat('policy', 'denythreshold') accepted_formats = config['policy']['acceptedfiles'].split(',') allowtie = config.getboolean('policy', 'allow_ties') bot = commands.Bot(command_prefix=prefix) # nude detector is not used unless in debug, so you can see why some images are deemed nsfw detector = NudeDetector() classifier = NudeClassifier() # cog loading @bot.event async def on_ready(): invlink = f"https://discord.com/oauth2/authorize?client_id={clientid}&permissions={botperms}&scope=bot" print(f"lewd stopper is ready, invite me at link {invlink}") if debug: print( "==== WARNING: DEBUG MODE IS ON! NO MESSAGES WILL BE DELETED.====\n==== FOR THIS BOT TO MODERATE PROPERLY, " "TURN OFF DEBUG IN CONFIG.INI ====") # this function will be ran async by the executor
import cv2 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:
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('')
import os import base64 from nudenet import NudeDetector detector = NudeDetector(os.getenv('MODEL_NAME', 'default')) """ Your function should take list of items as input This makes batching possible """ def predictor(in_images=[], batch_size=32): if not in_images: return [] preds = [] for in_img in in_images: try: preds.append(detector.detect(in_img)) except: preds.append(None) return preds if __name__ == "__main__": import json import pickle import base64
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
async def run(self, bot: kaizen85modules.KaizenBot): detector = None if not os.path.isfile(detector_model): bot.logger.log( "[ImageSearch] Can't find detector model file. NSFW check will not work." ) else: detector = NudeDetector(detector_model) class CommandImg(bot.module_handler.Command): name = "img" desc = "Поиск изображений в Google" args = "<поисковый запрос>" keys = ["no-nsfw-check"] async def run(self, message: discord.Message, args, keys): if len(args) < 1: return False keyword = " ".join(message.clean_content.split()[1:]) resp = google_images_download.googleimagesdownload() aip = resp.download( arguments={ "keywords": keyword, "limit": 1, "output_directory": "img_search", "no_directory": True }) if len(aip[next(iter(aip))]) < 1: await bot.send_error_embed( message.channel, "%s, изображение по запросу \"%s\" не найдено!" % (message.author.mention, keyword)) return True img_path = aip[next(iter(aip))][0] if len(img_path) < 1: await bot.send_error_embed( message.channel, "%s, произошла ошибка при загрузке картинки по запросу \"%s\"!" % (message.author.mention, keyword)) return True global is_nsfw is_nsfw = False # noinspection PyBroadException try: if not ("no-nsfw-check" in keys and bot.check_permissions(message.author.guild_permissions, ["administrator"]))\ and detector is not None: is_nsfw = True if len( detector.detect(img_path)) > 0 else False except Exception: pass with open(img_path, "rb") as f: img = discord.File(f, spoiler=is_nsfw) await message.channel.send( "Картинка по запросу \"%s\": (запросил: %s)%s%s" % (keyword, message.author.mention, "\n⚠️Обнаружен NSFW контент! Картинка спрятана под спойлер. Открывайте на свой страх и риск! ⚠️" if is_nsfw else "", "\n⚠️Проверка NSFW отключена! Проверьте логи. ⚠️" if not detector else ""), file=img) return True bot.module_handler.add_command(CommandImg(), self)
async def run(self, bot: kaizen85modules.KaizenBot): detector = None if not os.path.isfile(detector_model): bot.logger.log( "[ImageSearch] Can't find detector model file. NSFW check will not work." ) else: detector = NudeDetector(detector_model) cx = os.environ.get("kaizen_image_search_cx") api_key = os.environ.get("kaizen_image_search_apikey") if cx is None or api_key is None: bot.logger.log( "[ImageSearch] CX or API key are not available. Check \"kaizen_image_search_cx\" amd " "\"kaizen_image_search_apikey\" in PATH.") class CommandImg(bot.module_handler.Command): name = "img" desc = "Поиск изображений в Google" args = "<поисковый запрос>" keys = ["no-nsfw-check"] async def run(self, message: discord.Message, args, keys): if len(args) < 1: return False keyword = " ".join(message.clean_content.split()[1:]) try: resp = requests.get(request_url % (keyword, api_key, cx)) except Exception: await bot.send_error_embed( message.channel, "%s, произошла ошибка при загрузке картинки по запросу \"%s\"!" % (message.author.mention, keyword)) return True if resp.status_code != 200: await bot.send_error_embed( message.channel, "%s, произошла ошибка при загрузке картинки по запросу \"%s\": %s" % (message.author.mention, keyword, resp.text)) return True data = resp.json() if data["searchInformation"]["totalResults"] == "0": await bot.send_error_embed( message.channel, "%s, изображение по запросу \"%s\" не найдено!" % (message.author.mention, keyword)) return True img_path = "./img_search/%s.%s" % ( message.id, data["items"][0]["fileFormat"].split("/")[-1]) try: with open(img_path, "wb") as f: f.write(requests.get(data["items"][0]["link"]).content) except Exception: await bot.send_error_embed( message.channel, "%s, произошла ошибка при скачивании картинки по запросу \"%s\"!" % (message.author.mention, keyword)) return True global is_nsfw is_nsfw = False # noinspection PyBroadException try: if not ("no-nsfw-check" in keys and bot.check_permissions(message.author.guild_permissions, ["administrator"])) \ and detector is not None: is_nsfw = True if len( detector.detect(img_path)) > 0 else False except Exception: pass if is_nsfw and not message.channel.is_nsfw(): detector.censor(img_path, out_path=img_path, visualize=False) with open(img_path, "rb") as f: img = discord.File(f, spoiler=is_nsfw) await message.channel.send( "Картинка по запросу \"%s\": (запросил: %s)%s%s" % (keyword, message.author.mention if "anon" not in keys else "[данные удалены]", "\n⚠️Обнаружен NSFW контент! Картинка спрятана под спойлер. Открывайте на свой страх и риск! ⚠️" if is_nsfw else "", "\n⚠️Проверка NSFW отключена! Проверьте логи. ⚠️" if not detector else ""), file=img) return True bot.module_handler.add_command(CommandImg(), self)
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 os 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)
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
import cv2 import math import csv import numpy as np import random import os import glob from PIL import Image from nudenet import NudeDetector #from NudeNet_edited import Detector detector = NudeDetector() #detector = Detector() #You can change those folder paths rootdir = "./decensor_input" outdir_mosaics = "./decensor_input_mosaics" outdir_bars = "./decensor_input_bars" rejected = "./decensor_nudenet_rejected" os.makedirs(rootdir, exist_ok=True) os.makedirs(outdir_mosaics, exist_ok=True) os.makedirs(rejected, exist_ok=True) files = glob.glob(rootdir + '/**/*.png', recursive=True) files_jpg = glob.glob(rootdir + '/**/*.jpg', recursive=True) files.extend(files_jpg) err_files = [] def rand_color(): #color variation on 0, 1, or 2 of the 3 values. variation2 = random.randrange(0, 1) color_var = 0 if (random.random() >= .5): # half chance for white
# 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'])