예제 #1
0
    def _calculate_rain(self):
        """Rain is calculated differently when active and inactive.

        We have constant propability to change between states, and we also
        include previous value and clouds as a factor. Note, that there must
        be at least some clouds for rain to fall.

        """
        probability_change_state = 0.05

        # extracted booleans:
        change_state = random.uniform(0, 1) < probability_change_state
        is_raining = self.weather['rain'] > 0

        if self.weather['clouds'] > 0:
            if is_raining:
                if change_state:
                    self.weather['rain'] = 0

                else:
                    old_factor = 0.3
                    new_factor = 1 - old_factor

                    self.weather['rain'] = truncate(
                        self.weather['rain'] * old_factor +
                        self.weather['clouds'] * new_factor)
            else:
                if change_state and self.weather['clouds'] > 0.4:
                    self.weather['rain'] = truncate(self.weather['clouds'] *
                                                    0.2)
        else:
            self.weather['rain'] = 0
예제 #2
0
    def _calculate_clouds(self):
        """Clouds are calculated differently when active and inactive.

        We have different propabilities to change between states, and we also
        include previous value and wind as a factor.
        Altough, there is still a small chance of sudden storm or cleariness.

        Clouds have some critical value, and they tend to not pass through it.
        This allows us to simulate mainly moderate weather.

        """

        probability_stop = 0.1
        probability_start = 0.02
        probability_clear_all = 0.004
        probability_storm = 0.002
        probability_pass_critical = 0.9

        # extracted booleans:
        is_cloudy = self.weather['clouds'] > 0
        going_to_stop = random.uniform(0, 1) < probability_stop
        going_to_start = random.uniform(0, 1) < probability_start
        suddenly_clear_all = random.uniform(0, 1) < probability_clear_all
        suddenly_storm = random.uniform(0, 1) < probability_storm
        passing_critical = random.uniform(0, 1) < probability_pass_critical

        if is_cloudy:
            if suddenly_clear_all:
                self.weather['clouds'] = 0
            elif suddenly_storm:
                self.weather['clouds'] = random.uniform(0.8, 1)
            elif going_to_stop:
                self.weather['clouds'] = truncate(self.weather['clouds'] -
                                                  random.uniform(0.05, 0.2))
            else:
                old_factor = 0.95
                wind_factor = 0.2
                new_factor = 1 - old_factor

                new_cloud = random.betavariate(5, 1)
                # add new cloud
                clouds = (self.weather['clouds'] * old_factor +
                          new_cloud * new_factor)
                # consider influence of wind
                clouds -= self.weather['wind'] * wind_factor
                # go go over 0.4 with the probability of passing critical value
                upper_limit = 0.4
                if passing_critical:
                    upper_limit = 1
                # update clouds
                self.weather['clouds'] = truncate(clouds, 0, upper_limit)

        elif going_to_start:
            # start small, grow tall
            self.weather['clouds'] = random.uniform(0.05, 0.2)
예제 #3
0
    def _calculate_temperature(self):
        """Calculated based on all previous factors, base and tendency.

        Base is the additional bias, very slowly changing, simulating
        long-term weather conditions, such as atmospheric fronts.

        Tendency is a direction for the base - it can be increasing (+1)
        or decreasing (-1). Tendency has a slight chance to change at any
        point in time.

        Besides, temperature is computed including its previous value and some
        hard-coded weights for different factors.

        """

        # make changes in base temperature according to tendency
        change_tendency_probability = 0.001
        base_change_probability = 0.05

        tendency_changing = random.uniform(0, 1) < change_tendency_probability
        base_changing = random.uniform(0, 1) < base_change_probability

        if tendency_changing:
            self.tendency = -self.tendency
        if base_changing:
            old_factor = 0.9
            new_factor = 1 - old_factor

            new_base_temperature = random.randrange(5, 10) * self.tendency
            self.base_temperature = truncate(
                old_factor * self.base_temperature +
                new_factor * new_base_temperature, -20, 40)

        # Calculate all temperature factors with their weights.
        # there will be max 8 degrees warmer in a day
        day_heat = 8 * (sin(self.basetime / 230 + 300) / 2 + 0.5)
        sun_heat = 2 * self.weather['light']
        wind_chill = 5 * self.weather['wind']
        rain_chill = 3 * self.weather['rain']

        new_temp = (self.base_temperature + day_heat + sun_heat - wind_chill -
                    rain_chill)

        old_factor = 0.3
        new_factor = 1 - old_factor
        self.weather['temperature'] = truncate(
            old_factor * self.weather['temperature'] + new_factor * new_temp,
            -20, 40)
예제 #4
0
    def action_less_heating(self):
        """Action to be taken by RL-agent. Decrease heating level."""
        self.action_penalty = 1 if \
            self.devices_settings['heating_lvl'] == 0 else 0

        self.devices_settings['heating_lvl'] = round(
            truncate(self.devices_settings['heating_lvl'] - self.influence), 4)
예제 #5
0
    def action_more_cooling(self):
        """Action to be taken by RL-agent. Increase cooling level."""
        self.action_penalty = 1 if \
            self.devices_settings['cooling_lvl'] == 1 else 0

        self.devices_settings['cooling_lvl'] = round(
            truncate(self.devices_settings['cooling_lvl'] + self.influence), 4)
예제 #6
0
    def _calculate_temperature(self, outside_temp):
        """Updates the inside sensors with new temperature value.

        The new value depends on the last temperature, the outside temperature,
        house's isolation factor, and levels of heating and cooling devices.
        Value is truncated to <-20, 40> interval and this interval is assumed
        in the environment's normalization method -
        HouseEnergyEnvironment.serialize_state().

        Args:
            outside_temp(numeric): Unnormalized value of registered
                                   outside temperature

        Note: Currently, the sensor has no impact on the registered value, so
        every sensor would register the same value.
        """
        for data in self.inside_sensors.values():
            last_inside_temp = data['temperature']
            temp_delta = (outside_temp - last_inside_temp) \
                * (1 - self.house_isolation_factor)

            new_inside_temp = last_inside_temp \
                + self.timeframe \
                * (temp_delta + self.devices_settings['heating_lvl']
                    - self.devices_settings['cooling_lvl']) / 5

            data['temperature_delta'] = new_inside_temp - last_inside_temp
            data['temperature'] = truncate(new_inside_temp, -20, 40)
예제 #7
0
    def _calculate_light(self, outside_illumination):
        """Updates the inside sensors with new light value.

        Final light is normalized to <0, 1> interval and depends on the
        light device level, curtains level, outside light level and
        house_light_factor, which describes how much illumination 'enters'
        the house.

        Args:
            outside_illumination(numeric): Registered value of outside
                                           illumination

        Note: Currently, the sensor has no impact on the registered value, so
        every sensor would register the same value.
        """

        for data in self.inside_sensors.values():
            outside_light = (outside_illumination * self.house_light_factor) \
                * (1 - self.devices_settings['curtains_lvl'])

            inside_light = self.devices_settings['light_lvl'] \
                * self.max_led_illumination

            final_light = (outside_light + inside_light) \
                / self.max_led_illumination

            data['light'] = truncate(final_light)
예제 #8
0
def apertium_wiki(phenny, origterm, to_nick=None):
    term, section = wiki.parse_term(origterm)

    w = wiki.Wiki(endpoints, None)
    match = w.search(term)

    if not match:
        phenny.say('Can\'t find anything in the Apertium Wiki for "{0}".'.format(term))
        return

    snippet, url = wiki.extract_snippet(match, section)

    if to_nick:
        phenny.say(truncate(snippet, to_nick + ', "{}" - ' + url))
    else:
        phenny.say(truncate(snippet, '"{}" - ' + url))
예제 #9
0
def apertium_wiki(phenny, origterm, to_nick=None):
    term, section = wiki.parse_term(origterm)

    w = wiki.Wiki(endpoints, None)
    match = w.search(term)

    if not match:
        phenny.say('Can\'t find anything in the Apertium Wiki for "{0}".'.format(term))
        return

    snippet, url = wiki.extract_snippet(match, section)

    if to_nick:
        phenny.say(truncate(snippet, to_nick + ', "{}" - ' + url))
    else:
        phenny.say(truncate(snippet, '"{}" - ' + url))
예제 #10
0
def retrieve_commit(phenny, input):
    '''Retreive commit information for a given repository and revision. This
    command is called as 'begiak: info <repo> <rev>'.'''

    # get repo and rev with regex
    data = input.group(1).split(' ')

    if len(data) != 2:
        phenny.reply("Invalid number of parameters.")
        return

    repo = data[0]
    rev = data[1]

    if repo in phenny.config.svn_repositories:
        # we don't handle SVN; see modules/svnpoller.py for that
        return
    if repo not in phenny.config.git_repositories:
        phenny.reply("That repository is not monitored by me!")
        return
    try:
        info, url = get_commit_info(phenny, repo, rev)
    except:
        phenny.reply("Invalid revision value!")
        return
    # the * is for unpacking
    msg = generate_report(repo, *info)
    # the URL is truncated so that it has at least 6 sha characters
    url = url[:url.rfind('/') + 7]
    phenny.say(truncate(msg, '{} ' + url))
예제 #11
0
    def _calculate_light(self):
        """Light is calculated from sun and clouds"""
        clouds_factor = 0.7

        self.weather['light'] = truncate(self.weather['sun'] -
                                         (self.weather['clouds'] *
                                          clouds_factor))
예제 #12
0
파일: git.py 프로젝트: goavki/phenny
def retrieve_commit(phenny, input):
    '''Retreive commit information for a given repository and revision. This
    command is called as 'begiak: info <repo> <rev>'.'''

    # get repo and rev with regex
    data = input.group(1).split(' ')

    if len(data) != 2:
        phenny.reply("Invalid number of parameters.")
        return

    repo = data[0]
    rev = data[1]

    if repo in phenny.config.svn_repositories:
        # we don't handle SVN; see modules/svnpoller.py for that
        return
    if repo not in phenny.config.git_repositories:
        phenny.reply("That repository is not monitored by me!")
        return
    try:
        info, url = get_commit_info(phenny, repo, rev)
    except:
        phenny.reply("Invalid revision value!")
        return
    # the * is for unpacking
    msg = generate_report(repo, *info)
    # the URL is truncated so that it has at least 6 sha characters
    url = url[:url.rfind('/') + 7]
    phenny.say(truncate(msg, '{} ' + url))
예제 #13
0
def send_email(to, subject, body, signoff=None):
    if to:
        logging.info("Sending email to %s" % (to))
        subject = EMAIL_PREFIX + subject
        subject = tools.truncate(subject, 40)
        if signoff:
            body = body + signoff
        deferred.defer(mail.send_mail, to=to, sender=SENDER_EMAIL, subject=subject, body=body)
예제 #14
0
def format_email(e, list_name):
    subject = e['Subject']
    subject = re.sub(r"(=\?.*\?=)(?!$)", r"\1 ", subject)
    subject = str(make_header(decode_header(subject)))
    subject = subject.replace('['+list_name.capitalize()+'] ', '')

    # message = '{}: {} * {} * {}'.format(list_name, obfuscate_address(e['From']), subject, strip_reply_lines(e))
    message = '{}: {}: {}'.format(list_name, obfuscate_address(e['From']), subject)

    return truncate(message)
예제 #15
0
def send_email(to, subject, body, signoff=None):
    if to:
        subject = EMAIL_PREFIX + subject
        subject = tools.truncate(subject, 40)
        if signoff:
            body = body + signoff
        deferred.defer(mail.send_mail,
                       to=to,
                       sender=SENDER_EMAIL,
                       subject=subject,
                       body=body)
예제 #16
0
def format_email(e, list_name):
    subject = e['Subject']
    subject = re.sub(r"(=\?.*\?=)(?!$)", r"\1 ", subject)
    subject = str(make_header(decode_header(subject)))
    subject = subject.replace('[' + list_name.capitalize() + '] ', '')

    # message = '{}: {} * {} * {}'.format(list_name, obfuscate_address(e['From']), subject, strip_reply_lines(e))
    message = '{}: {}: {}'.format(list_name, obfuscate_address(e['From']),
                                  subject)

    return truncate(message)
예제 #17
0
    def _calculate_accumulated_energy(self, outside_illumination):
        """Calculates new value of energy accumulated in the battery

        Args:
            outside_illumination(numeric): Registered value of outside
                                           illumination
        """
        acc = outside_illumination * self.max_pv_absorption * self.timeframe
        self.battery['delta'] = acc
        self.battery['current'] = truncate(arg=(acc + self.battery['current']),
                                           upper=self.battery['max'])
예제 #18
0
def format_email(e, list_name):
    subject = decode_mime_utf(e['Subject'])
    subject = subject.replace('[' + list_name.capitalize() + '] ', '')

    from_address = decode_mime_utf(e['From'])

    # message = '{}: {} * {} * {}'.format(list_name, obfuscate_address(e['From']), subject, strip_reply_lines(e))
    message = '{}: {}: {}'.format(list_name, obfuscate_address(from_address),
                                  subject)

    return truncate(message)
예제 #19
0
파일: svnpoller.py 프로젝트: goavki/phenny
def recentcommits(phenny, input):
    """List the most recent SVN commits."""
    print("POLLING recent")
    for repo in phenny.config.svn_repositories:
        #phenny.say("{}: {}".format(repo, phenny.config.svn_repositories[repo]))
        poller = SVNPoller(repo, phenny.config.svn_repositories[repo])
        # for (msg, revisions) in pollers[repo].check(phenny.revisions):
        rev = poller.get_last_revision()
        msg = poller.generateReport(rev, True)
        url = poller.sourceforgeURL(rev)
        phenny.say(truncate(msg, '{} ' + url))
    print("POLLED recent")
예제 #20
0
파일: wikipedia.py 프로젝트: goavki/phenny
def wikipedia(phenny, origterm, lang, to_user=None):
    if not origterm:
        return phenny.say('Perhaps you meant ".wik Zen"?')

    origterm = origterm.strip()
    lang = lang.strip()

    term, section = wiki.parse_term(origterm)

    w = wiki.Wiki(endpoints, lang)
    match = w.search(term)

    if not match:
        phenny.say('Can\'t find anything in Wikipedia for "{0}".'.format(origterm))
        return

    snippet, url = wiki.extract_snippet(match, section)

    if to_user:
        phenny.say(truncate(snippet, to_user + ', "{}" - ' + url))
    else:
        phenny.say(truncate(snippet, '"{}" - ' + url))
예제 #21
0
    def action_less_light(self):
        """
        Action to be taken by RL-agent. Decrease lights level.
        Note that this action uses 2 times smaller influence as agent
        needs a bit more precision with the light settings.
        """

        self.action_penalty = 1 if \
            self.devices_settings['light_lvl'] == 0 else 0.05

        self.devices_settings['light_lvl'] = round(
            truncate(self.devices_settings['light_lvl'] - self.influence / 2),
            4)
예제 #22
0
파일: git.py 프로젝트: goavki/phenny
def get_recent_commit(phenny, input):
    '''Get recent commit information for each repository Begiak monitors. This
    command is called as 'begiak: recent'.'''

    for repo in phenny.config.git_repositories:
        html = web.get(phenny.config.git_repositories[repo] + '/commits')
        data = json.loads(html)
        # the * is for unpacking
        info, url = get_commit_info(phenny, repo, data[0]['sha'])
        msg = generate_report(repo, *info)
        # the URL is truncated so that it has at least 6 sha characters
        url = url[:url.rfind('/') + 7]
        phenny.say(truncate(msg, '{} ' + url))
예제 #23
0
def get_recent_commit(phenny, input):
    '''Get recent commit information for each repository Begiak monitors. This
    command is called as 'begiak: recent'.'''

    for repo in phenny.config.git_repositories:
        html = web.get(phenny.config.git_repositories[repo] + '/commits')
        data = json.loads(html)
        # the * is for unpacking
        info, url = get_commit_info(phenny, repo, data[0]['sha'])
        msg = generate_report(repo, *info)
        # the URL is truncated so that it has at least 6 sha characters
        url = url[:url.rfind('/') + 7]
        phenny.say(truncate(msg, '{} ' + url))
예제 #24
0
def wikipedia(phenny, origterm, lang, to_user=None):
    if not origterm:
        return phenny.say('Perhaps you meant ".wik Zen"?')

    origterm = origterm.strip()
    lang = lang.strip()

    term, section = wiki.parse_term(origterm)

    w = wiki.Wiki(endpoints, lang)
    match = w.search(term)

    if not match:
        phenny.say(
            'Can\'t find anything in Wikipedia for "{0}".'.format(origterm))
        return

    snippet, url = wiki.extract_snippet(match, section)

    if to_user:
        phenny.say(truncate(snippet, to_user + ', "{}" - ' + url))
    else:
        phenny.say(truncate(snippet, '"{}" - ' + url))
예제 #25
0
    def action_curtains_up(self):
        """
        Action to be taken by RL-agent. Increase the curtains level.
        Note that this action uses 2 times smaller influence as agent
        needs a bit more precision with the light settings.
        There is a small penalty for using this action, to prevent it
        from being used as an action_nop.
        """

        self.action_penalty = 1 if \
            self.devices_settings['curtains_lvl'] == 0 else 0.05

        self.devices_settings['curtains_lvl'] = round(
            truncate(self.devices_settings['curtains_lvl'] -
                     self.influence / 2), 4)
예제 #26
0
    def _calculate_sun(self):
        """Sun is calculated as a sinus between day start and end hour.

        Amplitude is set once per episode, and varies between <0.5, 1>

        """

        daystart = self.config['env']['day_start']
        dayend = self.config['env']['day_end']
        daylen = dayend - daystart
        sun = 0
        if daystart <= self.basetime <= dayend:
            sun = truncate(sin((self.basetime - daystart) * pi / daylen)) *\
                  self.sun_amplitude

        self.weather['sun'] = sun
예제 #27
0
def recentcommits(phenny, input):
    """List the most recent SVN commits."""
    print("POLLING!!!!")
    if phenny.config.svn_repositories is None:
        phenny.say(
            "SVN module cannot function without repositories being set in the config file!"
        )
        return
    for repo in phenny.config.svn_repositories:
        #phenny.say("{}: {}".format(repo, phenny.config.svn_repositories[repo]))
        poller = SVNPoller(repo, phenny.config.svn_repositories[repo])
        #for (msg, revisions) in pollers[repo].check(phenny.revisions):
        rev = poller.get_last_revision()
        msg = poller.generateReport(rev, True)
        url = poller.sourceforgeURL(rev)
        phenny.say(truncate(msg, '{} ' + url))
예제 #28
0
def vtluug(phenny, input):
    """.vtluug <term> - Look up something on the VTLUUG wiki."""

    origterm = input.group(1)

    if not origterm:
        return phenny.say('Perhaps you meant ".vtluug VT-Wireless"?')

    term, section = wiki.parse_term(origterm)

    w = wiki.Wiki(endpoints, None)
    match = w.search(term)

    if not match:
        phenny.say(
            'Can\'t find anything in the VTLUUG Wiki for "{0}".'.format(term))
        return

    snippet, url = wiki.extract_snippet(match, section)

    phenny.say(truncate(snippet, '"{}" - ' + url))
예제 #29
0
파일: svnpoller.py 프로젝트: goavki/phenny
def retrieve_commit_svn(phenny, input):
    data = input.group(1).split(' ')

    if len(data) != 2:
        phenny.reply("Invalid number of parameters.")
        return

    repo = data[0]
    rev = data[1]

    if repo in phenny.config.git_repositories:
        return

    if repo not in phenny.config.svn_repositories:
        phenny.reply("That repository is not monitored by me!")
        return

    poller = SVNPoller(repo, phenny.config.svn_repositories[repo])
    msg = poller.generateReport(rev, True)
    url = poller.sourceforgeURL(rev)
    phenny.say(truncate(msg, '{} ' + url))
예제 #30
0
def retrieve_commit_svn(phenny, input):
    data = input.group(1).split(' ')

    if len(data) != 2:
        phenny.reply("Invalid number of parameters.")
        return

    repo = data[0]
    rev = data[1]

    if repo in phenny.config.git_repositories:
        return

    if repo not in phenny.config.svn_repositories:
        phenny.reply("That repository is not monitored by me!")
        return

    poller = SVNPoller(repo, phenny.config.svn_repositories[repo])
    msg = poller.generateReport(rev, True)
    url = poller.sourceforgeURL(rev)
    phenny.say(truncate(msg, '{} ' + url))
예제 #31
0
파일: search.py 프로젝트: evo938938/gracie
def search(phenny, input):
    if not input.group(1):
        return phenny.reply('.search for what?')
    query = input.group(1)

    if not is_up('https://api.duckduckgo.com'):
        return phenny.say('Sorry, DuckDuckGo API is down.')

    r = requests.get(ddg_uri + query, timeout=REQUEST_TIMEOUT).json()
    try:
        answer = r['AbstractText']
        answer_url = r['AbstractURL']
        if answer == '':
            answer = r['RelatedTopics'][0]['Text']
            answer_url = r['RelatedTopics'][0]['FirstURL']
            if answer == '':
                return phenny.say('Sorry, no result.')
    except:
        return phenny.say('Sorry, no result.')
    # Removes html tags, if exist
    answer = re.sub('<.+?>', '', answer)
    phenny.say(truncate(answer, '{} - ' + answer_url))
예제 #32
0
    def draw_weather_widget(self):
        """Draws weather widget

        Widget has timer animation and five weather indicators:
        temperature and sun / wind / clouds / rain intensity.

        """

        # bg
        x = y = self.margin
        xmax = self.width * 3 // 7 - self.margin
        ymax = self.height - self.margin
        w = xmax - x
        h = ymax - y

        pygame.draw.rect(self.screen, self.colors['white'], (x, y, w, h))

        # small rects
        for i in range(1, 5):
            pygame.draw.rect(self.screen, self.colors['weather{}'.format(i)],
                             (x, y + (0.5 + i/10) * h, w, 0.11 * h))
        # circle
        radius = 0.19
        circle_center_x = x + 0.5 * w
        circle_center_y = y + 0.22 * h

        cur_time = self.data['Daytime']
        time_color_factor = cur_time / 720 if cur_time <= 720 else\
            2 - cur_time / 720

        color_daytime = pygame.Color(
            truncate(int(time_color_factor * 45 + 235), 0, 255),
            truncate(int(time_color_factor * 30 + 235), 0, 255),
            truncate(int(time_color_factor * 30 + 235), 0, 255)
        )

        for _radius, _color in ((radius + 0.01, self.colors['weather1']),
                                (radius - 0.01, color_daytime)):
            pygame.draw.circle(
                self.screen,
                _color, 
                (int(circle_center_x), int(circle_center_y)),
                int(_radius * w)
            )
        # time indicator (moving circle)
        pygame.draw.rect(
            self.screen, self.colors['weather1'],
            (int(circle_center_x - 0.01 * w),
             int(circle_center_y + radius * h * 0.7),
             0.02 * w, 0.035 * h)
        )
        daytime = self.data['Daytime']
        _phi = (daytime / 1440) * 2 * math.pi + math.pi / 2
        x_indicator = radius * math.cos(_phi)
        y_indicator = radius * math.sin(_phi)
        radius_indicator = 0.03

        for _radius, _color in ((radius_indicator, 'weather1'),
                                (radius_indicator - 0.01, 'weather5')):
            pygame.draw.circle(
                self.screen,
                self.colors[_color],
                (int(circle_center_x + x_indicator * w),
                 int(circle_center_y + y_indicator * w)),
                int(_radius * w)
            )
        # text - clock
        font_mono = pygame.font.Font(
            '../static/fonts/droid-sans-mono/DroidSansMono.ttf',
            int(0.05 * h)
        )
        color_daytime_clock = pygame.Color(
            truncate(200 - int(time_color_factor * (200 - 221)), 0, 255),
            truncate(200 - int(time_color_factor * (200 - 207)), 0, 255),
            truncate(200 - int(time_color_factor * (200 - 179)), 0, 255),
        )
        
        font_header = pygame.font.Font('../static/fonts/Lato/Lato-Regular.ttf',
                                       int(0.09 * h))

        time = [int(x) for x in divmod(daytime, 60)]
        time = "{:02}:{:02}".format(*time)
        self.draw_text(time, circle_center_x, circle_center_y,
                       color_daytime_clock, font_header, True)
        # text - blocks
        for _off, _data in enumerate(('Outside Light', 'Wind',
                                      'Clouds', 'Rain')):
            _label = _data.upper()
            if _data == 'Outside Light':
                _label = 'SUN'

            self.draw_text("{:<13}{:>5.0f}%".format(
                _label, self.data[_data] * 100),
                x + 0.57 * w, y + (0.65 + _off / 10) * h,
                self.colors['font'], font_mono, True)

        # text - temperature
        self.draw_text("{:<3.1f}°C".format(
                            self.data['Outside Temp']
                       ), x + 0.55 * w, y + 0.5 * h,
                       self.colors['weather5'], font_header, True)

        # weather icons
        for _off, _data in enumerate(('016-sun', '013-wind',
                                     '015-cloud', '010-raining')):
            self.draw_icon('../static/icons/weather/{}.png'.format(_data),
                           x + 0.1 * w, y + (0.65 + _off / 10) * h,
                           0.08 * h, 0.08 * h, self.colors['font'], True)

        self.draw_icon('../static/icons/weather/003-temperature.png',
                       x + 0.3 * w, y + 0.49 * h,
                       0.1 * h, 0.1 * h, self.colors['weather5'], True)

        # day / night icon
        if 6 * 60 < daytime < 19 * 60:
            daynight_icon = '../static/icons/weather/016-sun.png'
            daynight_color = self.colors['weather1']
        else:
            daynight_icon = '../static/icons/weather/004-moon.png'
            daynight_color = self.colors['weather3']

        self.draw_icon(daynight_icon,
                       x + 0.13 * w, y + 0.1 * h,
                       0.13 * h, 0.13 * h, daynight_color, True)
예제 #33
0
파일: git.py 프로젝트: goavki/phenny
    def do_POST_unsafe(self, data):
        '''Runs once per event. One repository. One event type.'''
        config = self.phenny.config

        default_channels = config.git_channels.get('*', config.channels)
        channels = default_channels

        # both commit reports and error reports
        messages = []

        repo = ''
        event = None

        # handle GitHub triggers
        if 'GitHub' in self.headers['User-Agent']:
            event = self.headers['X-Github-Event']
            user = data['sender']['login']

            if 'repository' in data:
                repo = data['repository']['name']
            elif 'organization' in data:
                repo = data['organization']['login'] + ' (org)'

            if config.git_events:
                full_name = data['repository']['full_name']
                event_types = []

                for key, value in config.git_events.items():
                    if fnmatch(full_name, key):
                        event_types = value
            else:
                event_types = None

            event_in_config = False
            if 'action' in data:
                for event_type in event_types:
                    if (event + '_' + data['action'] == event_type) or (event == event_type):
                        event_in_config = True

            if (event_types is not None) and ((event not in event_types) and (not event_in_config)):
                return [], []

            if config.git_channels:
                full_name = data['repository']['full_name']
                channels = []

                for key, value in config.git_channels.items():
                    if fnmatch(full_name, key):
                        channels = value

            if event == 'commit_comment':
                commit = data['comment']['commit_id'][:7]
                url = data['comment']['html_url']
                url = url[:url.rfind('/') + 7]
                action = data['action']

                if action == 'deleted':
                    template = '{:}: {:} * comment deleted on commit {:}: {:}'
                    messages.append(template.format(repo, user, commit, url))
                else:
                    template = '{:}: {:} * comment {:} on commit {:}: {:} {:}'
                    messages.append(truncate(
                        data['comment']['body'],
                        template.format(repo, user, action, commit, '{}', url)
                    ))
            elif event == 'create' or event == 'delete':
                template = '{:}: {:} * {:} {:} {:}d {:}'
                ref = data['ref']
                type_ = data['ref_type']
                messages.append(template.format(repo, user, type_, ref, event))
            elif event == 'fork':
                template = '{:}: {:} forked this repo {:}'
                url = data['forkee']['html_url']
                messages.append(template.format(repo, user, url))
            elif event == 'issue_comment':
                if 'pull_request' in data['issue']:
                    url = data['issue']['pull_request']['html_url']
                    text = 'pull request'
                else:
                    url = data['issue']['html_url']
                    text = 'issue'

                number = data['issue']['number']
                action = data['action']

                if action == 'deleted':
                    template = '{:}: {:} * comment deleted on {:} #{:}: {:}'
                    messages.append(template.format(repo, user, text, number, url))
                else:
                    template = '{:}: {:} * comment {:} on {:} #{:}: {:} {:}'
                    messages.append(truncate(
                        data['comment']['body'],
                        template.format(repo, user, action, text, number, '{}', url)
                    ))
            elif event == 'issues':
                template = '{:}: {:} * issue #{:} "{:}" {:} {:} {:}'

                number = data['issue']['number']
                title = data['issue']['title']
                action = data['action']
                url = data['issue']['html_url']
                opt = ''

                if data['issue']['assignee']:
                    opt += 'assigned to ' + data['issue']['assignee']['login']
                elif 'label' in data:
                    opt += 'with ' + data['label']['name']

                messages.append(template.format(repo, user, number, title, action, opt, url))
            elif event == 'member':
                template = '{:}: {:} * user {:} {:} as collaborator {:}'
                new_user = data['member']['login']
                action = data['action']
                messages.append(template.format(repo, user, new_user, action))
            elif event == 'membership':
                template = '{:}: user {:} {:} {:} {:} {:} {:}'
                new_user = data['member']['login']
                action = data['action']
                prep = ['to', 'from'][int(action == 'removed')]
                scope = data['scope']
                name = data['team']['name']
                messages.append(template.format(repo, new_user, action, prep, scope, name))
            elif event == 'pull_request':
                template = '{:}: {:} * pull request #{:} "{:}" {:} {:} {:}'
                number = data['number']
                title = data['pull_request']['title']
                action = data['action']
                url = data['pull_request']['html_url']
                opt = ''

                if data['pull_request']['assignee']:
                    opt = 'to ' + data['pull_request']['assignee']

                messages.append(template.format(repo, user, number, title, action, opt, url))
            elif event == 'pull_request_review_comment':
                template = '{:}: {:} * review comment deleted on pull request #{:}: {:}'
                number = data['pull_request']['number']
                url = data['comment']['html_url']
                action = data['action']

                if action == 'deleted':
                    messages.append(template.format(repo, user, number, url))
                else:
                    template = '{:}: {:} * review comment {:} on pull request #{:}: {:} {:}'
                    messages.append(truncate(
                        data['comment']['body'],
                        template.format(repo, user, action, number, '{}', url)
                    ))
            elif event == 'push':
                pusher_name = data['pusher']['name']

                if pusher_name in config.gitbots:
                    return [], []

                ref = data['ref'].split('/')[-1]
                repo_fullname = data['repository']['full_name']
                fork = data['repository']['fork']

                if ref != 'master' or fork:
                    try:
                        channels = config.branch_channels[repo_fullname][ref]
                    except:
                        return [], []

                template = '{:}: {:} [ {:} ] {:}: {:}'

                out_messages = []
                out_commithashes = []
                out_files = set()

                for commit in data['commits']:
                    out_commithashes.append(commit['id'][:7])
                    out_files.update(commit['modified'], commit['added'])
                    out_messages.append(commit['message'])

                messages.append(truncate(" * ".join(out_messages), template.format(
                    data['repository']['name'],
                    pusher_name,
                    ' '.join(out_commithashes),
                    ', '.join(out_files),
                    '{}'
                )))

            elif event == 'release':
                template = '{:}: {:} * release {:} {:} {:}'
                tag = data['release']['tag_name']
                action = data['action']
                url = data['release']['html_url']
                messages.append(template.format(repo, user, tag, action, url))
            elif event == 'repository':
                template = 'new repository {:} {:} by {:} {:}'
                name = data['repository']['name']
                action = data['action']
                url = data['repository']['url']
                messages.append(template.format(name, action, user, url, url))
            elif event == 'team_add':
                template = 'repository {:} added to team {:} {:}'
                name = data['repository']['full_name']
                team = data['team']['name']
                messages.append(template.format(name, team))
            elif event == 'ping':
                template = 'ping from {:}, org: {:}'

                if 'organization' in data:
                    org = data['organization']
                else:
                    org = "no org specified!"

                sender = data['sender']['login']
                messages.append(template.format(sender, org))

        elif 'Jenkins' in self.headers['User-Agent']:
            messages.append('Jenkins: {}'.format(data['message']))
        # not github or Jenkins
        elif "commits" in data:
            for commit in data['commits']:
                try:
                    if "author" in commit:
                        # for bitbucket
                        message = self.return_data("bitbucket", data, commit)
                        messages.append(message)
                    else:
                        # we don't know which site
                        message = "unsupported data: " + str(commit)
                        messages.append(message)
                except Exception:
                    logger.warning("unsupported data: " + str(commit))

        if not messages:
            # we couldn't get anything
            channels = default_channels

            if event:
                messages.append("Don't know about '" + event + "' events")
            else:
                messages.append("Unable to deal with unknown event")

        return channels, messages
예제 #34
0
파일: test_tools.py 프로젝트: goavki/phenny
 def test_truncate_short(self):
     text = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut."
     self.assertEqual(tools.truncate(text, max_length=100), text)
예제 #35
0
파일: test_tools.py 프로젝트: goavki/phenny
 def test_truncate_long(self):
     text = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut " \
     "labore et dolore magna aliquyam erat, sed diam voluptua."
     truncated = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt..."
     self.assertEqual(tools.truncate(text, max_length=100), truncated)
예제 #36
0
    def do_POST_unsafe(self, data):
        '''Runs once per event. One repository. One event type.'''
        config = self.phenny.config

        default_channels = config.git_channels.get('*', config.channels)
        channels = default_channels

        # both commit reports and error reports
        messages = []

        repo = ''
        event = None

        # handle GitHub triggers
        if 'GitHub' in self.headers['User-Agent']:
            event = self.headers['X-Github-Event']
            user = data['sender']['login']

            if 'repository' in data:
                repo = data['repository']['name']
            elif 'organization' in data:
                repo = data['organization']['login'] + ' (org)'

            if config.git_events:
                full_name = data['repository']['full_name']
                event_types = []

                for key, value in config.git_events.items():
                    if fnmatch(full_name, key):
                        event_types = value
            else:
                event_types = None

            event_in_config = False
            if 'action' in data:
                for event_type in event_types:
                    if (event + '_' + data['action']
                            == event_type) or (event == event_type):
                        event_in_config = True

            if (event_types is not None) and ((event not in event_types) and
                                              (not event_in_config)):
                return [], []

            if config.git_channels:
                full_name = data['repository']['full_name']
                channels = []

                for key, value in config.git_channels.items():
                    if fnmatch(full_name, key):
                        channels = value

            if event == 'commit_comment':
                commit = data['comment']['commit_id'][:7]
                url = data['comment']['html_url']
                url = url[:url.rfind('/') + 7]
                action = data['action']

                if action == 'deleted':
                    template = '{:}: {:} * comment deleted on commit {:}: {:}'
                    messages.append(template.format(repo, user, commit, url))
                else:
                    template = '{:}: {:} * comment {:} on commit {:}: {:} {:}'
                    messages.append(
                        truncate(
                            data['comment']['body'],
                            template.format(repo, user, action, commit, '{}',
                                            url)))
            elif event == 'create' or event == 'delete':
                template = '{:}: {:} * {:} {:} {:}d {:}'
                ref = data['ref']
                type_ = data['ref_type']
                messages.append(template.format(repo, user, type_, ref, event))
            elif event == 'fork':
                template = '{:}: {:} forked this repo {:}'
                url = data['forkee']['html_url']
                messages.append(template.format(repo, user, url))
            elif event == 'issue_comment':
                if 'pull_request' in data['issue']:
                    url = data['issue']['pull_request']['html_url']
                    text = 'pull request'
                else:
                    url = data['issue']['html_url']
                    text = 'issue'

                number = data['issue']['number']
                action = data['action']

                if action == 'deleted':
                    template = '{:}: {:} * comment deleted on {:} #{:}: {:}'
                    messages.append(
                        template.format(repo, user, text, number, url))
                else:
                    template = '{:}: {:} * comment {:} on {:} #{:}: {:} {:}'
                    messages.append(
                        truncate(
                            data['comment']['body'],
                            template.format(repo, user, action, text, number,
                                            '{}', url)))
            elif event == 'issues':
                template = '{:}: {:} * issue #{:} "{:}" {:} {:} {:}'

                number = data['issue']['number']
                title = data['issue']['title']
                action = data['action']
                url = data['issue']['html_url']
                opt = ''

                if data['issue']['assignee']:
                    opt += 'assigned to ' + data['issue']['assignee']['login']
                elif 'label' in data:
                    opt += 'with ' + data['label']['name']

                messages.append(
                    template.format(repo, user, number, title, action, opt,
                                    url))
            elif event == 'member':
                template = '{:}: {:} * user {:} {:} as collaborator {:}'
                new_user = data['member']['login']
                action = data['action']
                messages.append(template.format(repo, user, new_user, action))
            elif event == 'membership':
                template = '{:}: user {:} {:} {:} {:} {:} {:}'
                new_user = data['member']['login']
                action = data['action']
                prep = ['to', 'from'][int(action == 'removed')]
                scope = data['scope']
                name = data['team']['name']
                messages.append(
                    template.format(repo, new_user, action, prep, scope, name))
            elif event == 'pull_request':
                template = '{:}: {:} * pull request #{:} "{:}" {:} {:} {:}'
                number = data['number']
                title = data['pull_request']['title']
                action = data['action']
                url = data['pull_request']['html_url']
                opt = ''

                if data['pull_request']['assignee']:
                    opt = 'to ' + data['pull_request']['assignee']

                messages.append(
                    template.format(repo, user, number, title, action, opt,
                                    url))
            elif event == 'pull_request_review_comment':
                template = '{:}: {:} * review comment deleted on pull request #{:}: {:}'
                number = data['pull_request']['number']
                url = data['comment']['html_url']
                action = data['action']
                if action == 'deleted':
                    messages.append(template.format(repo, user, number, url))
                else:
                    template = '{:}: {:} * review comment {:} on pull request #{:}: {:} {:}'
                    try:
                        blacklist_pull_request_comment_users = config.blacklist_pull_request_comment_users
                    except AttributeError:
                        blacklist_pull_request_comment_users = ()
                    if user not in blacklist_pull_request_users:
                        messages.append(
                            truncate(
                                data['comment']['body'],
                                template.format(repo, user, action, number,
                                                '{}', url)))
            elif event == 'push':
                pusher_name = data['pusher']['name']

                if pusher_name in config.gitbots:
                    return [], []

                ref = data['ref'].split('/')[-1]
                repo_fullname = data['repository']['full_name']
                fork = data['repository']['fork']

                if ref != 'master' or fork:
                    try:
                        channels = config.branch_channels[repo_fullname][ref]
                    except:
                        return [], []

                template = '{:}: {:} [ {:} ] {:}: {:}'

                out_messages = []
                out_commithashes = []
                out_files = set()

                for commit in data['commits']:
                    out_commithashes.append(commit['id'][:7])
                    out_files.update(commit['modified'], commit['added'])
                    out_messages.append(commit['message'])

                messages.append(
                    truncate(
                        " * ".join(out_messages),
                        template.format(data['repository']['name'],
                                        pusher_name,
                                        ' '.join(out_commithashes),
                                        ', '.join(out_files), '{}')))

            elif event == 'release':
                template = '{:}: {:} * release {:} {:} {:}'
                tag = data['release']['tag_name']
                action = data['action']
                url = data['release']['html_url']
                messages.append(template.format(repo, user, tag, action, url))
            elif event == 'repository':
                template = 'new repository {:} {:} by {:} {:}'
                name = data['repository']['name']
                action = data['action']
                url = data['repository']['url']
                messages.append(template.format(name, action, user, url, url))
            elif event == 'team_add':
                template = 'repository {:} added to team {:} {:}'
                name = data['repository']['full_name']
                team = data['team']['name']
                messages.append(template.format(name, team))
            elif event == 'ping':
                template = 'ping from {:}, org: {:}'

                if 'organization' in data:
                    org = data['organization']
                else:
                    org = "no org specified!"

                sender = data['sender']['login']
                messages.append(template.format(sender, org))

        elif 'Jenkins' in self.headers['User-Agent']:
            messages.append('Jenkins: {}'.format(data['message']))
        # not github or Jenkins
        elif "commits" in data:
            for commit in data['commits']:
                try:
                    if "author" in commit:
                        # for bitbucket
                        message = self.return_data("bitbucket", data, commit)
                        messages.append(message)
                    else:
                        # we don't know which site
                        message = "unsupported data: " + str(commit)
                        messages.append(message)
                except Exception:
                    logger.warning("unsupported data: " + str(commit))

        if not messages:
            # we couldn't get anything
            channels = default_channels

            if event:
                messages.append("Don't know about '" + event + "' events")
            else:
                messages.append("Unable to deal with unknown event")

        return channels, messages