class BotMaintainance:
    utils: BotUtils
    database: BotDatabase
    profanity_filter: ProfanityFilter

    def __init__(self, database: BotDatabase, utils: BotUtils):
        self.utils = utils
        self.database = database
        self.profanity_filter = ProfanityFilter()
        self.profanity_filter.set_censor("^")

    async def handle_censor_channel(self,
                                    message_context: discord.Message) -> None:
        if await self.database.censored_channels.is_censored(
                message_context.channel.id):
            censored_message = self.profanity_filter.censor(
                message_context.content)
            if censored_message != message_context.content:
                await self.utils.messages.replace_message(
                    message_context, censored_message)
                await self.utils.messages.delete_message(message_context)

    async def handle_maintainance(self,
                                  message_context: discord.Message) -> None:
        await self.handle_censor_channel(message_context)
Exemplo n.º 2
0
def getAnalytics(transcript):
    participants_speaking_times = {}
    num_awkward_silences = 0 # 10+ seconds of silence
    #current_start_time = datetime.datetime.strptime('00:00:03.629', '%H:%M:%S.%f') # initialize to random value
    current_end_time = None # initialize to random value
    participants_polarity_subjectivity = {} # key: participant. value: [sum_polarity, sum_subjectivity, total_lines]
    num_profane_words = 0
    pf = ProfanityFilter()

    for line in transcript:
        current_start_time = datetime.datetime.strptime(line.start, '%H:%M:%S.%f')  # datetime.datetime.strptime(line[0:12], '%H:%M:%S.%f')
        if current_end_time != None and current_start_time - current_end_time > datetime.timedelta(seconds=10): # (current start) - (previous end)
            num_awkward_silences += 1
        current_end_time = datetime.datetime.strptime(line.end, '%H:%M:%S.%f')
        current_speaking_time = current_end_time - current_start_time
        participant_end_index = line.text.find(': ')
        if participant_end_index == -1:
            continue
        current_participant = line.text[0:participant_end_index]
        if current_participant in participants_speaking_times.keys():
            participants_speaking_times[current_participant] += current_speaking_time.total_seconds()
        else:
            participants_speaking_times[current_participant] = current_speaking_time.total_seconds()
        #current_speaking_time = datetime.datetime.strptime()
        #print(line)
        #for word in question_words:
        # Sentiment analysis
        testimonial = TextBlob(line.text[participant_end_index + 2:])
        if current_participant in participants_polarity_subjectivity.keys():
            participants_polarity_subjectivity[current_participant][0] += testimonial.sentiment.polarity
            participants_polarity_subjectivity[current_participant][1] += testimonial.sentiment.subjectivity
            participants_polarity_subjectivity[current_participant][2] += 1
        else:
            participants_polarity_subjectivity[current_participant] = [testimonial.sentiment.polarity, testimonial.sentiment.subjectivity, 1]
        # Check for profanity
        if pf.censor(line.text).find('*') != -1:
            for word in line.text.split(' '):
                if pf.censor(word).find('*') != -1:
                    num_profane_words += 1


    participants_average_sentiments = {} # key: participant. value: [average_polarity, average_subjectivity]
    for participant in participants_polarity_subjectivity.keys():
        participants_average_sentiments[participant] = [participants_polarity_subjectivity[participant][0]/participants_polarity_subjectivity[participant][2],
                                                        participants_polarity_subjectivity[participant][1]/participants_polarity_subjectivity[participant][2]]

    return participants_speaking_times, num_awkward_silences, participants_average_sentiments, num_profane_words
Exemplo n.º 3
0
def sanitize_strings(food_location, food_activity, food_duration):
    # This function detects errors in the user input field.
    profanity = False  # Do any strings contain profanity?
    time = False  # Is the time field out of range, or not a number?
    empty = False  # Are any strings empty?  < 10 chars
    long = False  # Are any strings > 128 chars

    max_activity_len = 100  # How long can a field be?
    max_location_len = 50
    min_activity_len = 10  # How short can a description be?
    min_location_len = 5  # How short can location description be?

    pf = ProfanityFilter()
    food_location_sanitized = pf.censor(food_location)
    food_activity_sanitized = pf.censor(food_activity)

    if food_location_sanitized != food_location:
        print("food_location: {}".format(food_location))
        print("food_location_sanitized: {}".format(food_location_sanitized))
        print("Mismatched. Censored contents detected.")
        profanity = True

    if food_activity_sanitized != food_activity:
        print("food_activity: {}".format(food_activity))
        print("food_activity_sanitized: {}".format(food_activity_sanitized))
        print("Mismatched. Censored contents detected.")
        profanity = True

    if '<script>' in food_activity or 'script' in food_location:
        print("<script> tag detected in input.")
        profanity = True

    if len(food_activity) > max_activity_len or len(
            food_location) > max_location_len:
        long = True

    if len(food_activity) < min_activity_len or len(
            food_location) < min_location_len:
        empty = True

    try:
        food_duration = float(food_duration)
    except:
        print("food_duration: {}".format(food_duration))
        print("Not a floating point number.")
        time = True
    if time is False and (food_duration > 4 or food_duration < 0.5):
        print(
            "Food duration of {} falls out of bounds. ".format(food_duration))
        time = True

    return {'profanity': profanity, 'time': time, 'empty': empty, 'long': long}
Exemplo n.º 4
0
    def response(self, flow: HTTPFlow):
        """The full HTTP response has been read."""
        data = ""
        try:
            data = flow.response.content.decode('utf8', errors='ignore')
        except UnicodeDecodeError as e:
            ctx.log.alert(str(e))

        with open(FILE_PROFANITY_BLOCKLIST) as f:
            profanity_filter_override = [line.strip()
                                         for line in f.readlines()]
            pf = ProfanityFilter(extra_censor_list=profanity_filter_override)
            flow.response.content = bytes(pf.censor(data), 'utf8')
Exemplo n.º 5
0
def post_check():
    pf = ProfanityFilter()
    if 'user_data' in session and len(request.form['message'].split(
            ' ')) / session['user_data']['public_repos'] <= 5:
        doc = {
            'fname': request.form['fname'],
            'lname': request.form['lname'],
            'message': pf.censor(request.form['message'])
        }
        collection.insert_one(doc)
        return render_template('message.html',
                               message='You successfully posted')
    return render_template(
        'message.html',
        message=
        'You failed to post due to too many words for your repository count')
Exemplo n.º 6
0
def create_message(subject: str = "Insight message!",
                   main_body: str = None) -> str:
    """
    Combines the given subject and main body to formulate an email message. Returns a str capable of being transmitted
    using smtplib and gmail. Uses a profanity filter to censor offensive content.
    :param subject: The subject (title/header) of the email.
    :param main_body: The main body of the email.
    :return: The constructed email to be sent.
    """
    # Check for type errors:
    if type(subject) is not str:  # Check the email subject
        raise TypeError("Expected type <class 'str'> got type ", type(subject),
                        " for subject")
    if type(main_body) is not str:  # Check the email body
        raise TypeError("Expected type <class 'str'> got type ",
                        type(main_body), " for main_body")
    message = f'Subject: {subject}\n{main_body}'  # Bundle the contents in the appropriate format
    profanity_filter = ProfanityFilter()  # Create ProfanityFilter object
    message = profanity_filter.censor(
        message)  # Censor offensive content from the message
    return message  # Return the constructed email
# In[3]:


from profanityfilter import ProfanityFilter


# In[4]:


pf = ProfanityFilter()


# In[5]:


pf.censor("That's bullshit!")


# In[6]:


pf.set_censor("@")


# In[7]:


pf.censor("That's bullshit!")


# In[8]:
Exemplo n.º 8
0
class VoteBot:
    def __init__(self, autovote=False, prompt="Chat \"!v (suggestion)\"!"):
        Settings.set_logger()
        self.host = None
        self.port = None
        self.auth = None
        capability = ["tags"]
        self.chan = None
        self.nick = None
        self.sending_message = True
        self.curr_prompt = prompt
        self.updated = mp.Value(c_bool, True)
        self.autovote = autovote
        self.log_results = True
        self.skip_voting = False
        self.random_collection = False
        self.collecting_time = 120
        self.voting_time = 120
        self.stream_delay = 2
        self.vote_cooldown = 120
        self.commands_collected_max = 5
        self.commands_collected = []
        self.votes_collected = []
        self.prompt = prompt
        self.min_msg_size = 5
        self.max_msg_size = 200

        with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "blacklist.txt"), "r") as f:
            censor = [l.replace("\n", "") for l in f.readlines()]
            self.pf = ProfanityFilter(custom_censor_list=censor)

        logging.debug("Setting settings.")
        Settings(self)

        logging.debug("Creating Database instance.")
        self.db = Database(self.chan)

        logging.debug("Creating TwitchWebsocket object.")
        self.ws = TwitchWebsocket(host=self.host,
                                  port=self.port,
                                  chan=self.chan,
                                  nick=self.nick,
                                  auth=self.auth,
                                  callback=self.message_handler,
                                  capability=capability,
                                  live=True)

        self.curr_mode = mp.Value(c_char, b's')
        logging.debug("Starting Websocket connection.")
        self.ws.start_blocking()

    def set_settings(self, host, port, chan, nick, auth, allowed_ranks, allowed_users):
        self.host, self.port, self.chan, self.nick, self.auth, self.allowed_ranks, self.allowed_users= host, port, chan, nick, auth, [rank.lower() for rank in allowed_ranks], [user.lower() for user in allowed_users]

    def not_bool(self, setting): # switches setting
        return not setting

    def extract_message(self, m):
        try:
            # Extract the message after the first space.
            return m.message[m.message.index(" ") + 1:]
        except ValueError:
            # If no spaces, return empty string
            return ""

    def check_permissions(self, m):
        # Gets users permissions for mod commands
        for rank in self.allowed_ranks:
            if rank in m.tags["badges"]:
                return True
        return m.user.lower() in self.allowed_users

    def check_mod_commands(self, m):
        if m.message.startswith("!cdtime"):
            # set cooldown between votes
            setting = self.is_int(m)
            if setting > 0: self.vote_cooldown = setting
            else: setting = self.vote_cooldown
            self.ws.send_message("Cooldown time (seconds): " + str(setting))

        elif m.message.startswith("!times"):
            # set all 3 phase times
            self.set_times(m)

        elif m.message.startswith("!vtime"):
            # set voting phase time
            setting = self.is_int(m)
            if setting > 0: self.voting_time = setting
            else: setting = self.voting_time
            self.ws.send_message("Voting time (seconds): " + str(setting))

        elif m.message.startswith(("!rand", "!random")):
            # sets random collection mode
            setting = self.not_bool(self.random_collection)
            self.random_collection = setting
            self.ws.send_message("Random Collection Mode: " + str(setting))

        elif m.message.startswith("!ctime"):
            # set collecting phase time
            setting = self.is_int(m)
            if setting > 0: self.collecting_time = setting
            else: setting = self.collecting_time
            self.ws.send_message("Collecting time (seconds): " + str(setting))

        elif m.message.startswith("!msg"):
            # set to have responses sent to chat
            setting = self.not_bool(self.sending_message)
            self.sending_message = setting
            self.ws.send_message("Sending chat messages: " + str(setting))

        elif m.message.startswith("!stop"):
            # end voting, remove HTML
            self.stop_vote()

        elif m.message.startswith("!start"):
            # start voting, display HTML
            self.begin_voting(self.extract_message(m), False)

        elif m.message.startswith("!autovote"):
            # turns on/off autovote
            setting = self.not_bool(self.autovote)
            self.autovote = setting
            self.ws.send_message("Autovote mode: " + str(setting))

        elif m.message.startswith("!max"):
            # sets max amount of suggestions
            setting = self.is_int(m)
            if setting > 0: self.commands_collected_max = setting
            else: setting = self.commands_collected_max
            self.ws.send_message("Max candidates: " + str(setting))

        elif m.message.startswith("!dtime"):
            # sets stream delay time
            setting = self.is_int(m)
            if setting > 0: self.stream_delay = setting
            else: setting = self.stream_delay
            self.ws.send_message("Stream delay (seconds): " + str(setting))

        elif m.message.startswith("!ballot"):
            # sends ballot.txt info to vote panel (optionally send custom vote phase time)
            self.send_ballot(m)

        elif m.message.startswith("!clear"):
            # stop voting and clear HTML
            self.clear_tables()

        elif m.message.startswith("!skip"):
            # turn on/off the voting phase
            setting = self.not_bool(self.skip_voting)
            self.skip_voting = setting
            self.ws.send_message("Skipping voting phase: " + str(setting))

        elif m.message.startswith("!r"):
            # removes a vote suggestion
            self.mod_remove_vote(m)

        elif m.message.startswith("!s"):
            # sets new default prompt and starts a vote
            # self.mod_command_send_next(self.extract_message(m))
            self.begin_voting(self.extract_message(m), True)

        else:
            return False

        return True

    def clear_html(self, m):
        # gets rid of html tags
        return m.replace("<", "").replace(">", "")

    def message_handler(self, m):
        if m.type == "366":
            logging.info(f"Successfully joined channel: #{m.channel}")
        elif m.type == "PRIVMSG":
            if self.check_permissions(m) and self.check_mod_commands(m): # check if command is a mod command first
                return
            elif m.message.lower().startswith(("!v", "!vote")): # main voting command
                if self.curr_mode.value in (b'r', b'c'): # if ready to collect or currently collecting
                    self.vote_command(m.user, self.clear_html(self.extract_message(m)).strip())
                elif self.curr_mode.value == b'v': # if in voting phase
                    vote = self.extract_message(m)
                    self.cast_vote(m.user, vote)

            elif self.curr_mode.value == b'v': # if in voting phase
                vote = m.message.strip()
                self.cast_vote(m.user, vote)

    def is_int(self, m):
        try:
            setting = int(self.extract_message(m))
            return setting
        except ValueError:
            self.ws.send_whisper(m.user, "Not a valid int.")
            return -1

    def set_times(self, m): # sets collecting, voting, and cooldown times
        def_times = [self.collecting_time, self.voting_time, self.vote_cooldown]
        try:
            times = self.extract_message(m).split()
            for i, time in enumerate(times):
                if i < len(def_times):
                    def_times[i] = int(time)
            # 1 to 3 numbers can be provided to set the times
            # 1st: collecting time, 2nd: voting time, 3rd: cooldown time
            self.collecting_time = def_times[0]
            self.voting_time = def_times[1]
            self.vote_cooldown = def_times[2]
            self.ws.send_message("Times (seconds) - Collection: " + str(self.collecting_time) + " | Voting: " + str(self.voting_time) + " | Cooldown: " + str(self.vote_cooldown))

        except Exception:
            print(Exception, ": Invalid times.")

    def clear_tables(self):
        self.curr_mode.value = b'l'
        self.display_clear()

    def mod_remove_vote(self, m): # used to clear a row to exclude it from the current collecting/voting phases
        pos = int(self.extract_message(m))
        if pos > 0 and pos <= len(self.commands_collected):
            if self.commands_collected[pos-1]:
                self.commands_collected[pos-1][2] = False

    def begin_voting(self, prompt=None, set_default=False):
        if self.curr_mode.value in (b'a', b's', b'l'):
            if prompt in ("", None):
                prompt = self.prompt
            elif set_default:
                self.prompt = prompt

            self.commands_collected = []
            self.votes_collected = []
            self.curr_prompt = prompt
            self.curr_mode.value = b'r'
            self.updated.value = True
            self.display_vote_start(prompt)
            return

        self.ws.send_message("Current vote isn't finished!")

    def stop_vote(self):
        self.curr_mode.value = b's'
        self.display_vote_stop()

    def display_vote_start(self, prompt):
        if self.sending_message:
            self.ws.send_message("Starting vote!")
            self.ws.send_message(prompt)

    def display_vote_stop(self):
        pass

    def display_clear(self):
        pass

    def send_ballot(self, m):
        # ballot.txt prompt and vote options set to be voted on
        # ballot.txt: line 1: prompt
        # other lines: suggestions to be voted on
        # any number sent with the command sets the vote phase time
        vote_time = self.is_int(m)
        if vote_time < 1:
            vote_time = self.voting_time

        if self.curr_mode.value in (b's', b'l'):
            self.commands_collected = []
            self.votes_collected = []
            f = open(os.getcwd() + "/ballot.txt")
            ballot = f.readlines()
            self.curr_prompt = ballot[0].strip()
            self.commands_collected = []
            for item in ballot[1:]:
                self.commands_collected.append([item.strip(), 0, True, "ballot"])

            self.updated.value = False
            self.curr_mode.value = b'v'
            self.display_vote_start(prompt_class="voting-prompt")
            self.start_vote_collector(False, False, vote_time)

    def mod_command_set_autovote(self, m):
        msg = self.extract_message(m)
        if msg.lower() in ("false", "0", "f"):
            self.autovote = False
        elif msg == "":
            self.autovote = self.not_bool(self.autovote)
        else:
            self.autovote = True

    def get_list_vote(self, key, list):
        for index, x in enumerate(list):
            if key.lower() == x[0].lower():
                return [index, x[1]]
        return False

    def mod_command_send_msg(self, m):
        msg = self.extract_message(m)
        if msg.lower() == "true":
            self.sending_message = True
        elif msg.lower() == "false":
            self.sending_message = False
        else:
            print("Failed to set send_msg value.")

    def command_cooldown(self, m):
        try:
            msg = int(self.extract_message(m))
            if msg > 0:
                self.cooldown = msg
                print("Changed cooldown to " + str(msg) + " seconds.")
            else:
                print("Error: Cooldown cannot be negative.")
        except:
            print("Error: Cooldown value invalid.")

    def censor(self, message):
        # Replace banned phrase with ***
        censored = self.pf.censor(message)
        if message != censored:
            logging.warning(f"Censored \"{message}\" into \"{censored}\".")
        return censored

    def vote_command(self, user, message): # Send a candidate to be voted on - or add to vote of already suggested one
        message = self.censor(message)
        ml = len(message)
        if ml >= self.min_msg_size and ml <= self.max_msg_size:
            if self.curr_mode.value == b'r':
                self.start_collecting()
            if self.curr_mode.value == b'c' and len(self.commands_collected) < self.commands_collected_max: # check if commands are still allowed
                self.add_command(user, message)

                if len(self.commands_collected) == self.commands_collected_max:
                    self.curr_mode.value = b'v'

                self.updated.value = False
            elif self.curr_mode.value == b'x': # random collection phase
                self.add_command(user, message)
        else: self.ws.send_message("@" + str(user) + " - Your message must be between " + str(self.min_msg_size) + " and " + str(self.max_msg_size) + " characters long.")

    def add_command(self, user, message):
        user_vote = self.get_list_vote(user, self.votes_collected)
        # if user has voted, check if the candidate exists and switch vote if it does
        # else, add candidate to list
        command_vote = self.get_list_vote(message, self.commands_collected)
        if command_vote: # if command exists, change user vote
            if user_vote:
                prev_vote = int(self.votes_collected[user_vote[0]][1]) - 1
                self.commands_collected[prev_vote][1] -= 1 # change previous vote count
                self.commands_collected[command_vote[0]][1] += 1 # increase vote count of selection
                self.votes_collected[user_vote[0]][1] = user_vote[1] # change vote selection
            else:
                self.commands_collected[command_vote[0]][1] += 1
        else:
            if user_vote:
                self.ws.send_message("@" + str(user) + " - You've already submitted a candidate and cannot submit another this round.")
                pass
            else:
                self.commands_collected.append([message, 1, True, user])
                self.votes_collected.append([user, len(self.commands_collected) - 1])

    def start_collecting(self): # on receiving first command, start the collecting timer
        if self.random_collection:
            self.curr_mode.value = b'x'
        else:
            self.curr_mode.value = b'c'
        command_collector = threading.Thread(target=self.command_collector,args=(self.curr_mode.value,),daemon=True)
        command_collector.start()

    def start_vote_collector(self, autovote, skip, timer):
        vote_collector = threading.Thread(target=self.vote_collector,args=(autovote,skip,timer),daemon=True)
        vote_collector.start()

    def command_collector(self, mode):
        self.wait_for_updates(self.collecting_time, mode, "collecting-prompt", skip_voting=self.skip_voting)
        if not self.curr_mode.value in (b's', b'l'): # start voting phase if not stopped
            if self.random_collection:
                self.get_random_commands()

            self.start_vote_collector(self.autovote, self.skip_voting, self.voting_time)
        elif self.log_results: # log results if collection stops before voting phase
            self.save_vote_log()

    def cast_vote(self, user, vote): # if vote is valid, add it to tally
        try:
            vote = int(vote)
        except ValueError:
            return

        vote_num = vote-1
        if vote_num < len(self.commands_collected):
            user_vote = self.get_list_vote(user, self.votes_collected)

            # if user has voted, change their vote selection and previous vote total
            if user_vote:
                self.commands_collected[user_vote[1]][1] -= 1
                self.votes_collected[user_vote[0]][1] = vote_num
            else:
                # else, add new vote
                self.votes_collected.append([user, vote_num])

            # increase vote count of selection
            self.commands_collected[vote_num][1] += 1
            self.updated.value = False

    def get_random_commands(self):
        # copies the current command list, and cuts it down to its max size with random items popped from it
        if len(self.commands_collected) > self.commands_collected_max:
            new_list = self.commands_collected[:]
            self.commands_collected = []
            selections = [*range(len(new_list))]
            for i in range(self.commands_collected_max):
                cmd_num = selections.pop(random.choice(range(len(selections))))
                for pos, vote in enumerate(self.votes_collected):
                    # changes votes to its new location on the list
                    if vote[1] == cmd_num: self.votes_collected[pos][1] = i + 1

                self.commands_collected.append(new_list[cmd_num])

            self.updated.value = False

    def votecount(self, a): # used for sorting the completed vote list
        return a[1]

    def wait_for_updates(self, duration, updating):
        start_time = time.time()
        i = duration
        delay = duration + self.stream_delay
        while i < delay and updating.value:
            time.sleep(1)
            i += 1

    def display_final_results(self):
        winner = self.get_winner()

        if self.sending_message:
            self.ws.send_message(winner_msg)
        else:
            print(winner_msg)

    def get_winner(self):
        if len(self.commands_collected) > 0 and not self.skip_voting:
            results_list = [x for x in self.commands_collected[:] if x[2]]
            results_list.sort(key=self.votecount, reverse=True)
            winner_list = []
            top_votes = results_list[0][1]
            for index, item in enumerate(self.commands_collected):
                if item[1] == top_votes:
                    winner_list.append([item, index])

            winner_msg = "Winner: "
            if len(winner_list) > 1:
                winner_msg += "Tie breaker - "
                winner = random.choice(winner_list)
            else:
                winner = winner_list[0]

            winner_msg +=  winner[0][0] + " | votes: " + str(winner[0][1])

            if self.sending_message:
                self.ws.send_message(winner_msg)
            else:
                print(winner_msg)

            return winner
        return False


    def wait_duration(duration, updating):
        pass

    def change_prompt(prompt, prompt_class):
        pass

    # saves votes and timestamps after a completed vote
    def save_vote_log(self):
        path = os.getcwd() + "/vote_logs.txt"
        try:
            timestamp = datetime.datetime.now()
            f = open(path, "a", encoding="utf-8")
            cmd_text = "\n" + "--" + str(timestamp) + "--" + "\n"
            cmd_text += self.curr_prompt + "\n" + "--------------" + "\n"
            for cmd in self.commands_collected:
                if not cmd[2]:
                    cmd_text += "**REMOVED** "

                cmd_text += cmd[0] + " - " + cmd[3]
                if not self.skip_voting:
                    cmd_text += " | votes: " + str(cmd[1])

                cmd_text += "\n"
            f.write(cmd_text)

        except:
            print("Failed saving vote log.")

    # displays candidates and time left (+stream delay) for voting
    def vote_collector(self, autovote, skip_voting, vote_timer):
        self.curr_mode.value = b'v'
        if not skip_voting:
            if len(self.commands_collected) > 1: # only vote if there is more than 1 item
                if self.sending_message:
                    self.ws.send_message("Type the number of the item to cast a vote!")
                self.wait_for_updates(vote_timer, b'v', "voting-prompt", skip_voting=skip_voting)

            if not self.curr_mode.value in (b's', b'l'):
                self.display_final_results()

        if self.log_results: # saves results to vote_logs.txt
            self.save_vote_log()

        if autovote and not self.curr_mode.value in (b's', b'l') : # autovote check, turns off if next vote starts
            self.curr_mode.value = b'a'
            self.wait_for_updates(self.vote_cooldown, b'a', "cooldown-prompt", use_delay=False, skip_voting=skip_voting)
            if self.curr_mode.value == b'a' and autovote:
                self.begin_voting()
Exemplo n.º 9
0
def censor(text):
    '''censor all offensive words with *'''
    pf = ProfanityFilter()
    pf.set_censor("*")
    censored = pf.censor(text)
    return censored
Exemplo n.º 10
0
class RewardsHandler:
  """A class for handling purchased rewards!"""

  def __init__(self, websockets, sound_manager, script_manager, light_manager, me_bot):
    self.queue = queue.Queue()
    self.websockets = websockets
    self.sound_manager = sound_manager
    self.script_manager = script_manager
    self.light_manager = light_manager
    self.voicemod_manager = VoicemodManager()
    self.me_bot = me_bot
    self.worker_thread = None
    self.filter = ProfanityFilter()
    self.all_sounds = {
      sound.name: sound.sound_file.path
      for sound in Sound.objects.filter(private=False)
    }
    self.rewards = {
      "79dcdf6f-7166-4958-8635-ba2233772008": self.sound_reward,
      "9fca547f-266a-4416-a6fe-f7ede97e4d97": self.shame_cube_reward,
      "5d02b71f-fceb-4ea8-9cca-9da2d749ebda": self.stream_message_reward,
      "529d7869-0bea-4503-9eba-0c59e9943782": self.scramble_camera_reward,
      "63438f03-3cea-4461-b7f3-dce44ba5c7da": self.grant_vip_reward,
      "ba256777-1cbc-4730-9b5c-0e16a1fd1086": self.revoke_vip_reward,
      "173af3e8-2bc0-4a52-adff-91c47c3e891a": self.change_light_color_reward,
      "53bf2ef4-0cbb-4cd6-b4e8-55c1c731c31a": self.light_wave_reward,
      "ac385b50-5be0-49da-bb6a-c95b9d18d9b2": self.change_background_image_reward,
      "00e8bfd4-d44d-4e85-8d45-088e2e09c639": self.birthday_reward,
      "259cdb66-6f68-4647-9671-9b1bb81b483d": self.voicemod_reward
    }
    self.start_worker()

  def start_worker(self):
    """Start the worker thread for processing the alerts queue."""
    self.worker_thread = StoppableThread(target=self.process_queue, daemon=True)
    self.worker_thread.start()

  def process_queue(self):
    """Process the alert queue, interesting logic is in async_process_queue."""
    self.loop = asyncio.new_event_loop()
    asyncio.set_event_loop(self.loop)

    asyncio.run(self.async_process_queue())

  async def async_process_queue(self):
    """Processes message from our alert queue."""

    while not self.worker_thread.stopped():
      # If redemptions aren't enabled, sleep and wait.
      if not await async_get_value(TWITCH_CHAT_REDEMPTIONS_ENABLED):
        await asyncio.sleep(5)
        continue

      reward = self.queue.get()
      await self.handle_reward(reward)
      self.queue.task_done()
      await asyncio.sleep(0.01)

  async def handle_reward(self, reward):
    """Process an individual reward."""
    await self.rewards[reward.reward_id](reward)

  async def shame_cube_reward(self, reward):
    """Process a purchased shame cube reward."""
    self.script_manager.run_and_wait("shame_cube")

  async def voicemod_reward(self, reward):
    """Processes a voicemod reward."""
    # If a thread is already active, we want to requeue the reward until the
    # 10 second timer is up.
    if self.voicemod_manager.thread_active:
      self.queue.put_nowait(reward)
      return

    self.voicemod_manager.change_voice()

  async def birthday_reward(self, reward):
    """Process a purchased confetti reward.

    I couldn't decide between calling it grunt birthday party and confetti but
    I think that more people will understand what confetti is, hence the double
    naming.
    """
    self.script_manager.run_and_wait("birthday_party")

  async def scramble_camera_reward(self, reward):
    """Scrambles the camera filter settings.

    Note that in this case we don't want to use the run_and_wait api.
    """
    self.script_manager.run_script("scramble_camera_filter")

  async def change_background_image_reward(self, reward):
    """Changes the background image."""
    url = get_random_photo_url(reward.message)
    if not url:
      return

    await async_set_value(BACKGROUND_IMAGE_URL, url)
    await self.websockets.background_image.send({"imageUrl": url})


  async def change_light_color_reward(self, reward):
    """Changes the light color of my smart lights."""
    self.light_manager.set_color_fuzzy(reward.message)

  async def light_wave_reward(self, reward):
    """L I G H T W A V E."""
    self.light_manager.set_waveform_fuzzy(reward.message)

  async def stream_message_reward(self, reward):
    """Updates the displayed stream message.

    Updates both the key value store and sends data over the websocket.
    """
    soup = BeautifulSoup(reward.message, features="html.parser")
    stripped = soup.get_text()
    message = replace_emotes_in_message(self.filter.censor(stripped), reward.emotes, size=1.0)
    await async_set_value(KING_OF_THE_HILL_MESSAGE, message)
    await async_set_value(KING_OF_THE_HILL_AUTHOR, reward.author)

    await self.websockets.king_of_the_hill.send({
      "author": reward.author,
      "message": message
    })

  async def sound_reward(self, reward):
    """Plays a custom sound.

    The sound selected matches the input message as best as possible.
    NOTE: "as best as possible" means not very well.
    """
    sound_name = sorted(
      self.all_sounds.keys(),
      key=lambda sound: fuzz.ratio(reward.message.lower(), sound.lower()),
      reverse=True
    )[0]

    self.sound_manager.play_sound(
      self.all_sounds[sound_name],
      sound_name=sound_name,
      mic=True,
      headphone=True
    )

  async def grant_vip_reward(self, reward):
    """Give 'em VIP."""
    await self.me_bot.send_message(f"/vip {reward.author}")

  async def revoke_vip_reward(self, reward):
    """Take their VIP away."""
    await self.me_bot.send_message(f"/unvip {reward.message.lower()}")

  async def queue_from_pubsub(self, data):
    """Queue a reward from pubsub.

    If the reward has user_input associated with it, skip it. That will be
    handled by queue_from_message.
    """
    if "user_input" in data["data"]["redemption"]:
      return

    reward = Reward(
      data["data"]["redemption"]["reward"]["id"],
      author=data["data"]["redemption"]["user"]["login"]
    )
    logger.info(reward)
    if reward.reward_id not in self.rewards:
      return

    self.queue.put_nowait(reward)
    return

  async def queue_from_message(self, message):
    """Queues a reward from a message.

    This is handled separately so we have easy access to emotes.
    """
    reward = Reward(
      message.tags["custom-reward-id"],
      author=message.author.name,
      message=message.content,
      emotes=message.tags.get("emotes")
    )
    self.queue.put_nowait(reward)
    return
Exemplo n.º 11
0
df = cur.fetchall()

df2 = []
for i in df:
    df2.append([i[0], i[1]])

df3 = pd.DataFrame(df2)
df3.columns = ['tweet_id', 'tweet_text']
df4 = []
for i, j in enumerate(df3['tweet_text']):
    tweet_id = df3['tweet_id'].iloc[i]
    text = df3['tweet_text'].iloc[i]
    sentiments = TextBlob(j)
    df4.append([
        tweet_id, text,
        pf.censor(j), sentiments.sentiment.polarity,
        sentiments.sentiment.subjectivity
    ])

df4 = pd.DataFrame(df4)
df4.columns = ['tweet_id', 'tweet_text', 'clean_text', 'sentiment', 'tone']

#print(df4)

#####################################################################################################################

conn = psycopg2.connect(database="final_project",
                        user="******",
                        password="******",
                        host="127.0.0.1",
                        port="5432")
Exemplo n.º 12
0
class TwitchAIDungeon:
    def __init__(self):
        # Initialize variables to None
        self.host = None
        self.port = None
        self.chan = None
        self.nick = None
        self.auth = None
        capability = ["tags"]
        self.access_token = None
        self.cooldown = 0
        self.last_command_time = 0
        self.allowed_ranks = []
        self.allowed_users = []
        self.custom_prompt = ""
        with open("blacklist.txt", "r") as f:
            censor = [l.replace("\n", "") for l in f.readlines()]
            self.pf = ProfanityFilter(custom_censor_list=censor)

        # Create an Api instance to connect to AI Dungeon 2.
        logging.debug("Creating API instance.")
        self.api = API(self)

        # Update variables
        logging.debug("Setting settings.")
        Settings(self)

        # Create a Database instance for storing which users do not want to be whispered
        logging.debug("Creating Database instance.")
        self.db = Database(self.chan)

        # Get the session_id
        self.session_id = self.api.get_session_id()

        # Create Websocket object
        logging.debug("Creating TwitchWebsocket object.")
        self.ws = TwitchWebsocket(host=self.host, 
                                  port=self.port,
                                  chan=self.chan,
                                  nick=self.nick,
                                  auth=self.auth,
                                  callback=self.message_handler,
                                  capability=capability,
                                  live=True)
        # Start a blocking websocket connection
        logging.debug("Starting Websocket connection.")
        self.ws.start_bot()

    def set_settings(self, host, port, chan, nick, auth, cooldown, access_token, allowed_ranks, allowed_users, custom_prompt):
        self.host, self.port, self.chan, self.nick, self.auth, self.cooldown, self.access_token, self.allowed_ranks, self.allowed_users, self.custom_prompt = host, port, chan, nick, auth, cooldown, access_token, [rank.lower() for rank in allowed_ranks], [user.lower() for user in allowed_users], custom_prompt

    def message_handler(self, m):
        if m.type == "366":
            logging.info(f"Successfully joined channel: #{m.channel}")
        elif m.type == "PRIVMSG":
            if m.message.startswith("!do"):
                self.command_do(m)
            elif m.message.startswith("!remember"):
                self.command_remember(m)
            elif m.message.startswith("!revert"):
                self.command_revert(m)
            elif m.message.startswith("!event"):
                self.command_event(m)
            elif m.message.startswith(("!say", "!talk", "!ask")):
                self.command_say(m)
            elif m.message.startswith("!help"):
                self.command_help(m)
            elif m.message.startswith("!restart") and self.check_permissions(m):
                self.command_restart(m)

    def extract_message(self, m):
        try:
            # Extract the message after the first space.
            return m.message[m.message.index(" ") + 1:]
        except ValueError:
            # If no spaces, return empty string
            return ""

    def check_permissions(self, m):
        for rank in self.allowed_ranks:
            if rank in m.tags["badges"]:
                return True
        return m.user.lower() in self.allowed_users

    def check_cooldown(self):
        # True iff it has been `self.cooldown` seconds since the last command use.
        return self.last_command_time + self.cooldown < time.time()

    def check_cooldown(self, m):
        # Difference is the amount of seconds remaining on the cooldown
        difference = self.last_command_time + self.cooldown - time.time()
        if difference <= 0:
            return True
        # If the cooldown has been hit, and the user has not said they don't want to be whispered, then whisper them the cooldown.
        if not self.db.check_whisper_ignore(m.user):
            out = f"Cooldown hit: {difference:.2f} out of {self.cooldown:.0f}s remaining. !nopm to stop these cooldown pm's."
            logging.debug(out)
            self.ws.send_whisper(m.user, out)
        return False

    def response_task(self, message, prefix, postfix, custom_output):
        # Get the actual output from the API
        out = self.api.say(prefix + message + postfix)

        # If a custom output is warranted for this action type, use that as output instead
        if custom_output:
            out = custom_output
        else:
            # Censor the output
            out = self.censor(out)
            
            # Convert to a better format, eg remove newlines.
            out = self.parse_output(out)

        if out:
            logging.info(f"Chat output: {out}")
            # If `out` could be considered a command, 
            # then prepend a space which does not get filtered out by twitch, 
            # which should prevent the message as being considered a command
            if out.startswith(("!", "~", ".", "/", "\\")):
                out = "Рађ" + out
            self.ws.send_message(out)
        else:
            out = "AI Dungeon 2 responded with an empty message, sadly."
            logging.error(out)
            self.ws.send_message(out)

    def command_action(self, message, prefix="", postfix="", custom_output="", force=False):
        # If force is True, then we will communicate with the API even if the message is empty.

        # Function to handle communication between API and this class
        if message or force:

            logging.debug(f"Calling api.say with \"{prefix + message + postfix}\"")
            # Check if the input contains a banned word
            if self.is_clean(message):
                # Set the last_command_time to the current time for cooldown
                self.last_command_time = time.time()

                # Create a threading daemon task for sending responses to the API
                t = threading.Thread(target=self.response_task, args=(message, prefix, postfix, custom_output), daemon=True)
                t.start()
                return
            
            logging.warning(f"The input \"{message}\" was filtered out.")
            out = "This input contained a banned word or phrase!"
        else:
            out = "Please also enter a message alongside your command."
        
        logging.info(f"Chat output: {out}")
        self.ws.send_message(out)

    def is_clean(self, message):
        # True if message does not contain a banned word.
        return self.pf.is_clean(message)

    def censor(self, message):
        # Replace banned phrase with ***
        censored = self.pf.censor(message)
        if message != censored:
            logging.warning(f"Censored \"{message}\" into \"{censored}\".")
        return censored

    def command_do(self, m):
        if self.check_cooldown(m):
            # Force is True for `!do`, as an empty message will allow more dialoge to generate on its own
            self.command_action(self.extract_message(m), force=True)

    def command_remember(self, m):
        #if self.check_cooldown(m):
        message = self.extract_message(m)
        self.command_action(message, prefix="/remember ", custom_output=f"Added \"{message}\" to game's memory.")

    def command_revert(self, m):
        # Note that reverting is not affected by the cooldown and can be done whenever.
        # TODO: Add a short cooldown to prevent two people from reverting at once, and reverting twice.
        self.command_action("/revert", custom_output=f"The last action has been reverted.")

    def command_event(self, m):
        if self.check_cooldown(m):
            self.command_action(self.extract_message(m), prefix="!")

    def command_say(self, m):
        if self.check_cooldown(m):
            self.command_action(self.extract_message(m), prefix="\"", postfix="\"")

    def command_help(self, m):
        self.ws.send_message("!do <text> to take an action. !remember <text> to remember `text`. !revert to revert the last action. !event <text> to have `text` occur. !say <text> to speak `text`.")

    def parse_output(self, message):
        # TODO: Improve upon this. 
        # Make it so conversations with different perspectives are clearly separated.
        return message.replace("\n", " ")

    def restart_task(self):
        # Get a new session_id and story from a new adventure
        session_id, story = self.api.start(self.custom_prompt)
        # Only if successful
        if session_id:
            self.session_id = session_id
            self.ws.send_message(story)
            logging.debug("Successfully started new story.")
            logging.info(story)
        else:
            self.ws.send_message("Failed to restart story.")
            logging.error("Failed to start new story.")

    def command_restart(self, m):
        # Set the last_command_time to the current time for cooldown
        self.last_command_time = time.time()

        # Asyncronously start a new story
        t = threading.Thread(target=self.restart_task, daemon=True)
        t.start()
Exemplo n.º 13
0
                    inline[i].text = text
                
                
#print (profanityFilter("this thing motherfuckin' sucks sucks f*****g stuff"))
from docx import Document
filename = "Hello12.docx"
doc = Document(filename)
for word in words:
    
"""
with open('text.txt', 'r') as myfile:
    data=myfile.read()
from profanityfilter import ProfanityFilter
pf = ProfanityFilter()
#print(pf.censor("That's bullshit!"))
from load_words import bad_words_list_final as words
pf.append_words(words)
filename = "Hello12.docx"
#doc = Document(filename)
#for p in doc.paragraphs:
    #inline=p.runs
    #for i in range(len(inline)):
        #y=inline[i].text
        #print(pf.censor(y))
        
        
data_filter=pf.censor(data)
f = open('filter.txt','w')
f.write(data_filter)
f.close()
#print(pf.censor('Unbuttoned, butt, buttoned'))