예제 #1
0
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
예제 #2
0
    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)
예제 #3
0
    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)
예제 #4
0
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
    ]
예제 #5
0
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
예제 #6
0
    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)
예제 #7
0
# 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
예제 #8
0
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:
예제 #9
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('')
예제 #10
0
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
예제 #11
0
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
예제 #12
0
    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)
예제 #13
0
    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)
예제 #14
0
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
예제 #15
0
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)
예제 #16
0
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
예제 #17
0
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
예제 #18
0
# 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'])