<commit_before>"""webui -- mostly-automatically generate a simple web interface.

"""

import jinja2
import logging
import datetime
import requests
import functools
from idiotic import dispatcher, event, items, scenes, utils
from idiotic.item import Toggle, Trigger, Number, Motor
from idiotic.scene import Scene

MODULE_NAME = "webui"

LOG = logging.getLogger("module.webui")

USE_GRAPHS = False

try:
    import pygal
    USE_GRAPHS = True
except:
    LOG.warning("Could not import pygal; graphs are disabled")

SECT_INCLUDE = ("include_tags",
                "exclude_tags",
                "include_items",
                "exclude_items")

include_tags = set()
exclude_tags = set()
default_graph = False
asset_path = None

env = None

template_args = {}

def configure(config, api, assets):
    global include_tags, exclude_tags, asset_path, env, template_args
    global default_graph

    template_args["title"] = config.get("page_title", "idiotic")
    template_args["root"] = api.path

    default_graph = config.get("enable_graph", False)

    asset_path = assets
    env = jinja2.Environment(loader=jinja2.FileSystemLoader(asset_path))

    api.serve(_main_js, '/main.js', content_type="text/javascript")
    api.serve(_sparkline, '/sparkline/<item>.svg', content_type="image/svg+xml")
    api.serve(_graph, '/graph/<item>.svg', content_type="image/svg+xml", get_args=True)

    traverse(api, "/", config)

    return

def traverse(api, path, tree):
    if not tree:
        return

    sections = []
    if "sections" in tree:
        sections = tree["sections"]
    else:
        sections = [{k: tree[k] for k in tree
                     if k in SECT_INCLUDE }]

    api.serve(functools.partial(_main_page, sections),
              path, content_type="text/html")

    for key, val in tree.get("subpages", {}):
        traverse(api, utils.join_url(path, key), val)

def scene(name, command=None, **kwargs):
    scene = getattr(scenes, name)
    if command == "enter":
        scene.enter()
    elif command == "exit":
        scene.exit()
    elif command is not None:
        raise NameError("Command '{}' does not exist on scene {}".format(
            command, scene))
    return scene.active

def _main_page(sections, *_, **__):
    args = dict(template_args)
    args["sections"] = []
    for section in sections:
        include_tags, exclude_tags, include_items, exclude_items = (
            set(section.get(n, [])) for n in SECT_INCLUDE
        )
        sect = {"item_list": []}
        sect.update({k: v for k, v in section.items()
                     if k not in SECT_INCLUDE})

        for item in sorted(list(items.all()) + list(scenes.all()), key=lambda i:i.name):
            if not _include_item(item, include_tags, exclude_tags,
                                 include_items, exclude_items):
                continue

            item_dict = {
                "desc": item.name,
                "name": utils.mangle_name(item.name),
                "show_disable": "webui.show_disable" in item.tags,
                "show_sparkline": "webui.show_sparkline" in item.tags,
                "enable_graph": default_graph,
                "state": getattr(item, "state", getattr(item, "active", None)),
                "disabled": not getattr(item, "enabled", False)
            }

            if "webui.enable_graph" in item.tags:
                item_dict["enable_graph"] = True
            elif "webui.disable_graph" in item.tags:
                item_dict["enable_graph"] = False

            if isinstance(item, Number):
                item_dict["inputs"] = [{"command": "set",
                                        "type": "number"}]
            elif isinstance(item, Toggle):
                item_dict["inputs"] = [{"command": "on",
                                        "type": "button"},
                                       {"command": "off",
                                        "type": "button"},
                                       {"command": "toggle",
                                        "type": "button"}]
            elif isinstance(item, Trigger):
                item_dict["inputs"] = [{"command": "trigger",
                                        "type": "button"}]
            elif isinstance(item, Motor):
                item_dict["inputs"] = [{"command": "forward",
                                        "type": "button"},
                                       {"command": "reverse",
                                        "type": "button"},
                                       {"command": "stop",
                                        "type": "button"}]
            elif isinstance(item, Scene):
                item_dict["inputs"] = [{"type": "scene"}]
            else:
                item_dict["inputs"] = []

            sect["item_list"].append(item_dict)
        args["sections"].append(dict(sect))

    return env.get_template('main.html').render(**args)

def _main_js(*_, **__):
    return env.get_template('main.js').render()

def __empty_svg():
    return """<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg
xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1 1"
width="1" height="1" id="svg_pixel"> </svg>"""

def _sparkline(item, *args, **kwargs):
    if USE_GRAPHS:
        history = items[item].state_history
        if not history:
            return __empty_svg()

        _, values = zip(*history.last(min(10, len(history))))

        graph = pygal.Line(interpolate='cubic', style=pygal.style.LightStyle)
        graph.add("Last 10", values)
        return graph.render_sparkline(height=25).decode('UTF-8')
    else:
        return __empty_svg()

def __avg_time(datetimes):
    total = sum(dt.hour * 3600 + dt.minute * 60 + dt.second for dt in datetimes)
    avg = total / len(datetimes)
    minutes, seconds = divmod(int(avg), 60)
    hours, minutes = divmod(minutes, 60)
    return datetime.datetime.combine(datetime.date(1900, 1, 1), datetime.time(hours, minutes, seconds))

def __group(times, values, count=50, group=lambda v: sum(v)/len(v)):
    if len(times) != len(values):
        raise ValueError("times and values must have same length")

    if len(times) < count or len(times) < 2:
        return times, values

    count = min(count, len(times))

    diff = (times[-1] - times[0]) / count

    divisions = [times[0] + i * diff for i in range(count)] + [times[-1]]

    temp = []

    res = []

    partitions = zip(divisions[0:], divisions[1:])

    i = 0
    for start, end in partitions:
        while i < len(times) and start <= times[i] <= end:
            temp.append((times[i], values[i]))
            i += 1
        else:
            if temp:
                ts, vs = zip(*temp)
                res.append((__avg_time(ts), group(vs)))
            temp = []

    return zip(*res)

def _graph(item, *args, time=86400, offset=0, count=None, **kwargs):
    if USE_GRAPHS:
        history = items[item].state_history
        if not history:
            return __empty_svg()

        if count:
            times, values = zip(*history.last(min(10, len(history))))
        else:
            times, values = zip(*history.since(datetime.datetime.now() - datetime.timedelta(seconds=int(time))))

        times, values = __group(times, values)

        graph = pygal.Line(style=pygal.style.LightStyle, x_label_rotation=-60)
        graph.title = items[item].name
        graph.add("Value", values)
        graph.x_labels = (t.strftime("%H:%M:%S") for t in times)
        return graph.render().decode('UTF-8')
    else:
        return __empty_svg()

def _include_item(item, include_tags, exclude_tags, include_items, exclude_items):
    return ((not include_tags or set(item.tags) & include_tags) or
            (item.name in include_items or
             utils.mangle_name(item.name) in include_items)) and \
            (not exclude_tags or not set(item.tags) & exclude_tags) and \
            (not exclude_items or (item.name not in exclude_items and
                                   utils.mangle_name(item.name) not in exclude_items))
<commit_msg>Add text widget support for webui<commit_after>"""webui -- mostly-automatically generate a simple web interface.

"""

import jinja2
import logging
import datetime
import requests
import functools
from idiotic import dispatcher, event, items, scenes, utils
from idiotic.item import Toggle, Trigger, Number, Motor, Text
from idiotic.scene import Scene

MODULE_NAME = "webui"

LOG = logging.getLogger("module.webui")

USE_GRAPHS = False

try:
    import pygal
    USE_GRAPHS = True
except:
    LOG.warning("Could not import pygal; graphs are disabled")

SECT_INCLUDE = ("include_tags",
                "exclude_tags",
                "include_items",
                "exclude_items")

include_tags = set()
exclude_tags = set()
default_graph = False
asset_path = None

env = None

template_args = {}

def configure(config, api, assets):
    global include_tags, exclude_tags, asset_path, env, template_args
    global default_graph

    template_args["title"] = config.get("page_title", "idiotic")
    template_args["root"] = api.path

    default_graph = config.get("enable_graph", False)

    asset_path = assets
    env = jinja2.Environment(loader=jinja2.FileSystemLoader(asset_path))

    api.serve(_main_js, '/main.js', content_type="text/javascript")
    api.serve(_sparkline, '/sparkline/<item>.svg', content_type="image/svg+xml")
    api.serve(_graph, '/graph/<item>.svg', content_type="image/svg+xml", get_args=True)

    traverse(api, "/", config)

    return

def traverse(api, path, tree):
    if not tree:
        return

    sections = []
    if "sections" in tree:
        sections = tree["sections"]
    else:
        sections = [{k: tree[k] for k in tree
                     if k in SECT_INCLUDE }]

    api.serve(functools.partial(_main_page, sections),
              path, content_type="text/html")

    for key, val in tree.get("subpages", {}):
        traverse(api, utils.join_url(path, key), val)

def scene(name, command=None, **kwargs):
    scene = getattr(scenes, name)
    if command == "enter":
        scene.enter()
    elif command == "exit":
        scene.exit()
    elif command is not None:
        raise NameError("Command '{}' does not exist on scene {}".format(
            command, scene))
    return scene.active

def _main_page(sections, *_, **__):
    args = dict(template_args)
    args["sections"] = []
    for section in sections:
        include_tags, exclude_tags, include_items, exclude_items = (
            set(section.get(n, [])) for n in SECT_INCLUDE
        )
        sect = {"item_list": []}
        sect.update({k: v for k, v in section.items()
                     if k not in SECT_INCLUDE})

        for item in sorted(list(items.all()) + list(scenes.all()), key=lambda i:i.name):
            if not _include_item(item, include_tags, exclude_tags,
                                 include_items, exclude_items):
                continue

            item_dict = {
                "desc": item.name,
                "name": utils.mangle_name(item.name),
                "show_disable": "webui.show_disable" in item.tags,
                "show_sparkline": "webui.show_sparkline" in item.tags,
                "enable_graph": default_graph,
                "state": getattr(item, "state", getattr(item, "active", None)),
                "disabled": not getattr(item, "enabled", False)
            }

            if "webui.enable_graph" in item.tags:
                item_dict["enable_graph"] = True
            elif "webui.disable_graph" in item.tags:
                item_dict["enable_graph"] = False

            if isinstance(item, Number):
                item_dict["inputs"] = [{"command": "set",
                                        "type": "number"}]
            elif isinstance(item, Text):
                item_dict["inputs"] = [{"command": "set",
                                        "type": "text"}]
            elif isinstance(item, Toggle):
                item_dict["inputs"] = [{"command": "on",
                                        "type": "button"},
                                       {"command": "off",
                                        "type": "button"},
                                       {"command": "toggle",
                                        "type": "button"}]
            elif isinstance(item, Trigger):
                item_dict["inputs"] = [{"command": "trigger",
                                        "type": "button"}]
            elif isinstance(item, Motor):
                item_dict["inputs"] = [{"command": "forward",
                                        "type": "button"},
                                       {"command": "reverse",
                                        "type": "button"},
                                       {"command": "stop",
                                        "type": "button"}]
            elif isinstance(item, Scene):
                item_dict["inputs"] = [{"type": "scene"}]
            else:
                item_dict["inputs"] = []

            sect["item_list"].append(item_dict)
        args["sections"].append(dict(sect))

    return env.get_template('main.html').render(**args)

def _main_js(*_, **__):
    return env.get_template('main.js').render()

def __empty_svg():
    return """<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg
xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1 1"
width="1" height="1" id="svg_pixel"> </svg>"""

def _sparkline(item, *args, **kwargs):
    if USE_GRAPHS:
        history = items[item].state_history
        if not history:
            return __empty_svg()

        _, values = zip(*history.last(min(10, len(history))))

        graph = pygal.Line(interpolate='cubic', style=pygal.style.LightStyle)
        graph.add("Last 10", values)
        return graph.render_sparkline(height=25).decode('UTF-8')
    else:
        return __empty_svg()

def __avg_time(datetimes):
    total = sum(dt.hour * 3600 + dt.minute * 60 + dt.second for dt in datetimes)
    avg = total / len(datetimes)
    minutes, seconds = divmod(int(avg), 60)
    hours, minutes = divmod(minutes, 60)
    return datetime.datetime.combine(datetime.date(1900, 1, 1), datetime.time(hours, minutes, seconds))

def __group(times, values, count=50, group=lambda v: sum(v)/len(v)):
    if len(times) != len(values):
        raise ValueError("times and values must have same length")

    if len(times) < count or len(times) < 2:
        return times, values

    count = min(count, len(times))

    diff = (times[-1] - times[0]) / count

    divisions = [times[0] + i * diff for i in range(count)] + [times[-1]]

    temp = []

    res = []

    partitions = zip(divisions[0:], divisions[1:])

    i = 0
    for start, end in partitions:
        while i < len(times) and start <= times[i] <= end:
            temp.append((times[i], values[i]))
            i += 1
        else:
            if temp:
                ts, vs = zip(*temp)
                res.append((__avg_time(ts), group(vs)))
            temp = []

    return zip(*res)

def _graph(item, *args, time=86400, offset=0, count=None, **kwargs):
    if USE_GRAPHS:
        history = items[item].state_history
        if not history:
            return __empty_svg()

        if count:
            times, values = zip(*history.last(min(10, len(history))))
        else:
            times, values = zip(*history.since(datetime.datetime.now() - datetime.timedelta(seconds=int(time))))

        times, values = __group(times, values)

        graph = pygal.Line(style=pygal.style.LightStyle, x_label_rotation=-60)
        graph.title = items[item].name
        graph.add("Value", values)
        graph.x_labels = (t.strftime("%H:%M:%S") for t in times)
        return graph.render().decode('UTF-8')
    else:
        return __empty_svg()

def _include_item(item, include_tags, exclude_tags, include_items, exclude_items):
    return ((not include_tags or set(item.tags) & include_tags) or
            (item.name in include_items or
             utils.mangle_name(item.name) in include_items)) and \
            (not exclude_tags or not set(item.tags) & exclude_tags) and \
            (not exclude_items or (item.name not in exclude_items and
                                   utils.mangle_name(item.name) not in exclude_items))
<|endoftext|>


<commit_before>#!/usr/bin/env python
# vim: set ts=4 sw=4 expandtab sts=4:
# Copyright (c) 2011-2012 Christian Geier, David Soulayrol
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
The pycarddav abstract model and tools for VCard handling.
"""

from __future__ import print_function

try:
    import base64
    import sys
    import vobject
    from collections import defaultdict

except ImportError, error:
    print(error)
    sys.exit(1)

def list_clean(string):
    """ transforms a comma seperated string to a list, stripping whitespaces
    "HOME, WORK,pref" -> ['HOME', 'WORK', 'pref']

    string: string of comma seperated elements
    returns: list()
    """

    string = string.split(',')
    rstring = list()
    for element in string:
        rstring.append(element.strip(' '))
    return rstring

NO_STRINGS = [u"n", "n", u"no", "no"]
YES_STRINGS = [u"y", "y", u"yes", "yes"]

PROPERTIES = ['EMAIL', 'TEL']
PROPS_ALL = ['FN', 'N', 'VERSION', 'NICKNAME', 'PHOTO', 'BDAY', 'ADR',
             'LABEL', 'TEL', 'EMAIL', 'MAILER', 'TZ', 'GEO', 'TITLE', 'ROLE',
             'LOGO', 'AGENT', 'ORG', 'NOTE', 'REV', 'SOUND', 'URL', 'UID',
             'KEY', 'CATEGORIES', 'PRODID', 'REV', 'SORT-STRING', 'SOUND',
             'URL', 'VERSION', 'UTC-OFFSET']
PROPS_ALLOWED = ['NICKNAME', 'BDAY', 'ADR', 'LABEL', 'TEL', 'EMAIL',
                 'MAILER', 'TZ', 'GEO', 'TITLE', 'ROLE', 'AGENT',
                 'ORG', 'NOTE', 'REV', 'SOUND', 'URL', 'UID', 'KEY',
                 'CATEGORIES', 'PRODID', 'REV', 'SORT-STRING', 'SOUND',
                 'URL', 'VERSION', 'UTC-OFFSET']
PROPS_ONCE = ['FN', 'N', 'VERSION']
PROPS_LIST = ['NICKNAME', 'CATEGORIES']
PROPS_BIN = ['PHOTO', 'LOGO', 'SOUND', 'KEY']

RTEXT = '\x1b[7m'
NTEXT = '\x1b[0m'
BTEXT = '\x1b[1m'

def get_names(display_name):
    first_name, last_name = '', display_name

    if display_name.find(',') > 0:
        # Parsing something like 'Doe, John Abraham'
        last_name, first_name = display_name.split(',')

    elif display_name.find(' '):
        # Parsing something like 'John Abraham Doe'
        # TODO: This fails for compound names. What is the most common case?
        name_list = display_name.split(' ')
        last_name = ''.join(name_list[-1])
        first_name = ' '.join(name_list[:-1])

    return first_name.strip().capitalize(), last_name.strip().capitalize()

def vcard_from_vobject(vcard):
    vdict = VCard()
    if vcard.name != "VCARD":
        raise Exception  # TODO proper Exception type
    for line in vcard.getChildren():
        # this might break, was tried/excepted before
        line.transformFromNative()
        property_name = line.name
        property_value = line.value

        try:
            if line.ENCODING_paramlist == [u'b']:
                property_value = base64.b64encode(line.value)

        except AttributeError:
            pass
        if type(property_value) == list:
            property_value = (',').join(property_value)

        vdict[property_name].append((property_value, line.params,))
    return vdict

def vcard_from_string(vcard_string):
    """
    vcard_string: str() or unicode()
    returns VCard()
    """
    try:
        vcard = vobject.readOne(vcard_string)
    except vobject.base.ParseError as error:
        raise Exception(error)  # TODO proper exception
    return vcard_from_vobject(vcard)

def vcard_from_email(display_name, email):
    fname, lname = get_names(display_name)
    vcard = vobject.vCard()
    vcard.add('n')
    vcard.n.value = vobject.vcard.Name(family=lname, given=fname)
    vcard.add('fn')
    vcard.fn.value = display_name
    vcard.add('email')
    vcard.email.value = email
    vcard.email.type_param = 'INTERNET'
    return vcard_from_vobject(vcard)

def cards_from_file(cards_f):
    collector = list()
    for vcard in vobject.readComponents(cards_f):
        collector.append(vcard_from_vobject(vcard))
    return collector

class VCard(defaultdict):
    """
    internal representation of a VCard. This is dict with some
    associated methods,
    each dict item is a list of tuples
    i.e.:
    >>> vcard['EMAIL']
    [('hanz@wurst.com', ['WORK', 'PREF']), ('hanz@wurst.net', ['HOME'])]

    h_ref: unique id (really just the url) of the VCard
    db_path: database file from which to initialize the VCard

    self.edited:
        0: nothing changed
        1: name and/or fname changed
        2: some property was deleted
    """

    def __init__(self, ddict=''):

        if ddict == '':
            defaultdict.__init__(self, list)
        else:
            defaultdict.__init__(self, list, ddict)
        self.href = ''
        self.edited = 0

    def serialize(self):
        return self.items().__repr__()

    @property
    def name(self):
        return unicode(self['N'][0][0]) if self['N'] else ''

    @name.setter
    def name(self, value):
        if not self['N']:
            self['N'] = [('', {})]
        self['N'][0][0] = value

    @property
    def fname(self):
        return unicode(self['FN'][0][0])

    @fname.setter
    def fname(self, value):
        self['FN'][0] = (value, {})

    def alt_keys(self):
        keylist = self.keys()
        for one in [x for x in ['FN', 'N', 'VERSION'] if x in keylist]:
            keylist.remove(one)
        keylist.sort()
        return keylist

    def print_email(self):
        """prints only name, email and type for use with mutt"""
        collector = list()
        try:
            for one in self['EMAIL']:
                try:
                    typelist = ','.join(one[1][u'TYPE'])
                except KeyError:
                    typelist = ''
                collector.append(one[0] + "\t" + self.fname + "\t" + typelist)
            return '\n'.join(collector)
        except KeyError:
            return ''

    def print_tel(self):
        """prints only name, email and type for use with mutt"""
        collector = list()
        try:
            for one in self['TEL']:
                try:
                    typelist = ','.join(one[1][u'TYPE'])
                except KeyError:
                    typelist = ''
                collector.append(self.fname + "\t" + one[0] + "\t" + typelist)
            return '\n'.join(collector)
        except KeyError:
            return ''

    @property
    def pretty(self):
        return self._pretty_base(self.alt_keys())

    @property
    def pretty_min(self):
        return self._pretty_base(['TEL', 'EMAIL'])

    def _pretty_base(self, keylist):
        collector = list()
        collector.append('\n' + BTEXT + 'Name: ' + self.fname + NTEXT)
        for key in keylist:
            for value in self[key]:
                try:
                    types = ' (' + ', '.join(value[1]['TYPE']) + ')'
                except KeyError:
                    types = ''
                line = key + types + ': ' + value[0]
                collector.append(line)
        return '\n'.join(collector)

    def _line_helper(self, line):
        collector = list()
        for key in line[1].keys():
            collector.append(key + '=' + ','.join(line[1][key]))
        if collector == list():
            return ''
        else:
            return (';' + ';'.join(collector))

    @property
    def vcf(self):
        collector = list()
        collector.append('BEGIN:VCARD')
        collector.append('VERSION:3.0')
        for key in ['FN', 'N']:
            collector.append(key + ':' + self[key][0][0])
        for prop in self.alt_keys():
            for line in self[prop]:

                types = self._line_helper(line)
                collector.append(prop + types + ':' + line[0])
        collector.append('END:VCARD')
        return '\n'.join(collector)
<commit_msg>Do not fail if FN is empty<commit_after>#!/usr/bin/env python
# vim: set ts=4 sw=4 expandtab sts=4:
# Copyright (c) 2011-2012 Christian Geier, David Soulayrol
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
The pycarddav abstract model and tools for VCard handling.
"""

from __future__ import print_function

try:
    import base64
    import sys
    import vobject
    from collections import defaultdict

except ImportError, error:
    print(error)
    sys.exit(1)

def list_clean(string):
    """ transforms a comma seperated string to a list, stripping whitespaces
    "HOME, WORK,pref" -> ['HOME', 'WORK', 'pref']

    string: string of comma seperated elements
    returns: list()
    """

    string = string.split(',')
    rstring = list()
    for element in string:
        rstring.append(element.strip(' '))
    return rstring

NO_STRINGS = [u"n", "n", u"no", "no"]
YES_STRINGS = [u"y", "y", u"yes", "yes"]

PROPERTIES = ['EMAIL', 'TEL']
PROPS_ALL = ['FN', 'N', 'VERSION', 'NICKNAME', 'PHOTO', 'BDAY', 'ADR',
             'LABEL', 'TEL', 'EMAIL', 'MAILER', 'TZ', 'GEO', 'TITLE', 'ROLE',
             'LOGO', 'AGENT', 'ORG', 'NOTE', 'REV', 'SOUND', 'URL', 'UID',
             'KEY', 'CATEGORIES', 'PRODID', 'REV', 'SORT-STRING', 'SOUND',
             'URL', 'VERSION', 'UTC-OFFSET']
PROPS_ALLOWED = ['NICKNAME', 'BDAY', 'ADR', 'LABEL', 'TEL', 'EMAIL',
                 'MAILER', 'TZ', 'GEO', 'TITLE', 'ROLE', 'AGENT',
                 'ORG', 'NOTE', 'REV', 'SOUND', 'URL', 'UID', 'KEY',
                 'CATEGORIES', 'PRODID', 'REV', 'SORT-STRING', 'SOUND',
                 'URL', 'VERSION', 'UTC-OFFSET']
PROPS_ONCE = ['FN', 'N', 'VERSION']
PROPS_LIST = ['NICKNAME', 'CATEGORIES']
PROPS_BIN = ['PHOTO', 'LOGO', 'SOUND', 'KEY']

RTEXT = '\x1b[7m'
NTEXT = '\x1b[0m'
BTEXT = '\x1b[1m'

def get_names(display_name):
    first_name, last_name = '', display_name

    if display_name.find(',') > 0:
        # Parsing something like 'Doe, John Abraham'
        last_name, first_name = display_name.split(',')

    elif display_name.find(' '):
        # Parsing something like 'John Abraham Doe'
        # TODO: This fails for compound names. What is the most common case?
        name_list = display_name.split(' ')
        last_name = ''.join(name_list[-1])
        first_name = ' '.join(name_list[:-1])

    return first_name.strip().capitalize(), last_name.strip().capitalize()

def vcard_from_vobject(vcard):
    vdict = VCard()
    if vcard.name != "VCARD":
        raise Exception  # TODO proper Exception type
    for line in vcard.getChildren():
        # this might break, was tried/excepted before
        line.transformFromNative()
        property_name = line.name
        property_value = line.value

        try:
            if line.ENCODING_paramlist == [u'b']:
                property_value = base64.b64encode(line.value)

        except AttributeError:
            pass
        if type(property_value) == list:
            property_value = (',').join(property_value)

        vdict[property_name].append((property_value, line.params,))
    return vdict

def vcard_from_string(vcard_string):
    """
    vcard_string: str() or unicode()
    returns VCard()
    """
    try:
        vcard = vobject.readOne(vcard_string)
    except vobject.base.ParseError as error:
        raise Exception(error)  # TODO proper exception
    return vcard_from_vobject(vcard)

def vcard_from_email(display_name, email):
    fname, lname = get_names(display_name)
    vcard = vobject.vCard()
    vcard.add('n')
    vcard.n.value = vobject.vcard.Name(family=lname, given=fname)
    vcard.add('fn')
    vcard.fn.value = display_name
    vcard.add('email')
    vcard.email.value = email
    vcard.email.type_param = 'INTERNET'
    return vcard_from_vobject(vcard)

def cards_from_file(cards_f):
    collector = list()
    for vcard in vobject.readComponents(cards_f):
        collector.append(vcard_from_vobject(vcard))
    return collector

class VCard(defaultdict):
    """
    internal representation of a VCard. This is dict with some
    associated methods,
    each dict item is a list of tuples
    i.e.:
    >>> vcard['EMAIL']
    [('hanz@wurst.com', ['WORK', 'PREF']), ('hanz@wurst.net', ['HOME'])]

    h_ref: unique id (really just the url) of the VCard
    db_path: database file from which to initialize the VCard

    self.edited:
        0: nothing changed
        1: name and/or fname changed
        2: some property was deleted
    """

    def __init__(self, ddict=''):

        if ddict == '':
            defaultdict.__init__(self, list)
        else:
            defaultdict.__init__(self, list, ddict)
        self.href = ''
        self.edited = 0

    def serialize(self):
        return self.items().__repr__()

    @property
    def name(self):
        return unicode(self['N'][0][0]) if self['N'] else ''

    @name.setter
    def name(self, value):
        if not self['N']:
            self['N'] = [('', {})]
        self['N'][0][0] = value

    @property
    def fname(self):
        return unicode(self['FN'][0][0]) if self['FN'] else ''

    @fname.setter
    def fname(self, value):
        self['FN'][0] = (value, {})

    def alt_keys(self):
        keylist = self.keys()
        for one in [x for x in ['FN', 'N', 'VERSION'] if x in keylist]:
            keylist.remove(one)
        keylist.sort()
        return keylist

    def print_email(self):
        """prints only name, email and type for use with mutt"""
        collector = list()
        try:
            for one in self['EMAIL']:
                try:
                    typelist = ','.join(one[1][u'TYPE'])
                except KeyError:
                    typelist = ''
                collector.append(one[0] + "\t" + self.fname + "\t" + typelist)
            return '\n'.join(collector)
        except KeyError:
            return ''

    def print_tel(self):
        """prints only name, email and type for use with mutt"""
        collector = list()
        try:
            for one in self['TEL']:
                try:
                    typelist = ','.join(one[1][u'TYPE'])
                except KeyError:
                    typelist = ''
                collector.append(self.fname + "\t" + one[0] + "\t" + typelist)
            return '\n'.join(collector)
        except KeyError:
            return ''

    @property
    def pretty(self):
        return self._pretty_base(self.alt_keys())

    @property
    def pretty_min(self):
        return self._pretty_base(['TEL', 'EMAIL'])

    def _pretty_base(self, keylist):
        collector = list()
        collector.append('\n' + BTEXT + 'Name: ' + self.fname + NTEXT)
        for key in keylist:
            for value in self[key]:
                try:
                    types = ' (' + ', '.join(value[1]['TYPE']) + ')'
                except KeyError:
                    types = ''
                line = key + types + ': ' + value[0]
                collector.append(line)
        return '\n'.join(collector)

    def _line_helper(self, line):
        collector = list()
        for key in line[1].keys():
            collector.append(key + '=' + ','.join(line[1][key]))
        if collector == list():
            return ''
        else:
            return (';' + ';'.join(collector))

    @property
    def vcf(self):
        collector = list()
        collector.append('BEGIN:VCARD')
        collector.append('VERSION:3.0')
        for key in ['FN', 'N']:
            collector.append(key + ':' + self[key][0][0])
        for prop in self.alt_keys():
            for line in self[prop]:

                types = self._line_helper(line)
                collector.append(prop + types + ':' + line[0])
        collector.append('END:VCARD')
        return '\n'.join(collector)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import sys, os.path, warnings, configparser
from configobj import ConfigObj
from .command import (command)
from .misc import (openappend)
from .help import (welcommessage)

# Kaidoku starts here

def main(argv=sys.argv[1:]):

    # Read system configuration from data/system.ini
    inifile = configparser.ConfigParser()
    here = os.path.abspath(os.path.dirname(__file__))
    inifile.read(os.path.join(here, 'data/system.ini'))
    version = inifile.get('system', 'version')
    ConfFile = os.path.expanduser(inifile.get('file', 'config'))

    # Read user configuration
    config = readconfig(ConfFile)

    # Kaidoku command line
    if (len(sys.argv)) == 1:
        print (welcommessage(version))
        while True:
            try:
                arg = input('kaidoku-'+version+'> ').strip().split()
            except:
                print ('\nQuitting kaidoku.')
                return
            if arg[0] == 'q':
                print ('Quitting kaidoku.')
                return
            config = command(arg, config)
            config.write()
    else:
        arg = sys.argv[1:]
        config = command(arg, config)
        config.write()
        return

# Read configuration

def readconfig(ConfFile):
    config = ConfigObj(os.path.expanduser(ConfFile), encoding='utf-8')
    if 'datadir' in config:
        datadir = os.path.expanduser(config['datadir'])
        if not os.path.isdir(datadir):
            try:
                os.mkdir(datadir)
            except:
                print ('Error: directory cannot be created.', datadir)
                datadir = ''
    else:
        datadir = ''
    config['datadir'] = datadir
    if 'file' in config:
        file =  os.path.expanduser(config["file"])
        try:
            input = open(file, 'r')
            input.close()
        except:
            out = openappend (file)
            if out == '':
                print ('Cannot open file:', file)
                sys.exit()
            out.close
        config["file"] = file
    else:
        file = os.path.abspath(os.path.dirname(__file__))+'/data/sudoku.txt'
        config["file"] = file
    if 'file2' in config:
        file2 =  os.path.expanduser(config["file2"])
    else:
        if file != '':
            name, ext = os.path.splitext(file)
            file2 = name + '2' + ext
            config["file2"] = file2
        else:
            file2 = ''
    if 'giveup' in config:
        giveup =  os.path.expanduser(config["giveup"])
    else:
        giveup = ''
        config["giveup"] = giveup
    if 'level' in config:
        level = config["level"]
    else:
        level = 2
        config["level"] = level
    if 'maxtime' in config:
        maxtime = config["maxtime"]
    else:
        maxtime = 60
        config["maxtime"] = maxtime
    if 'pointer' in config:
        pointer = config["pointer"]
    else:
        pointer = [''] + [1] * 9
        config["pointer"] = pointer
    if 'move' in config:
        move = config["move"]
    else:
        config["move"] = []
    if 'bookmark' in config:
        bookmark = config["bookmark"]
    else:
        bookmark = {}
        config["bookmark"] = bookmark
    config.write()
    return config
<commit_msg>Corrected by autopep8<commit_after># -*- coding: utf-8 -*-
import sys
import os.path
import warnings
import configparser
from configobj import ConfigObj
from .command import (command)
from .misc import (openappend)
from .help import (welcommessage)

# Kaidoku starts here

def main(argv=sys.argv[1:]):

    # Read system configuration from data/system.ini
    inifile = configparser.ConfigParser()
    here = os.path.abspath(os.path.dirname(__file__))
    inifile.read(os.path.join(here, 'data/system.ini'))
    version = inifile.get('system', 'version')
    ConfFile = os.path.expanduser(inifile.get('file', 'config'))

    # Read user configuration
    config = readconfig(ConfFile)

    # Kaidoku command line
    if (len(sys.argv)) == 1:
        print(welcommessage(version))
        while True:
            try:
                arg = input('kaidoku-' + version + '> ').strip().split()
            except:
                print('\nQuitting kaidoku.')
                return
            if arg[0] == 'q':
                print('Quitting kaidoku.')
                return
            config = command(arg, config)
            config.write()
    else:
        arg = sys.argv[1:]
        config = command(arg, config)
        config.write()
        return

# Read configuration

def readconfig(ConfFile):
    config = ConfigObj(os.path.expanduser(ConfFile), encoding='utf-8')
    if 'datadir' in config:
        datadir = os.path.expanduser(config['datadir'])
        if not os.path.isdir(datadir):
            try:
                os.mkdir(datadir)
            except:
                print('Error: directory cannot be created.', datadir)
                datadir = ''
    else:
        datadir = ''
    config['datadir'] = datadir
    if 'file' in config:
        file = os.path.expanduser(config["file"])
        try:
            input = open(file, 'r')
            input.close()
        except:
            out = openappend(file)
            if out == '':
                print('Cannot open file:', file)
                sys.exit()
            out.close
        config["file"] = file
    else:
        file = os.path.abspath(os.path.dirname(__file__)) + '/data/sudoku.txt'
        config["file"] = file
    if 'file2' in config:
        file2 = os.path.expanduser(config["file2"])
    else:
        if file != '':
            name, ext = os.path.splitext(file)
            file2 = name + '2' + ext
            config["file2"] = file2
        else:
            file2 = ''
    if 'giveup' in config:
        giveup = os.path.expanduser(config["giveup"])
    else:
        giveup = ''
        config["giveup"] = giveup
    if 'level' in config:
        level = config["level"]
    else:
        level = 2
        config["level"] = level
    if 'maxtime' in config:
        maxtime = config["maxtime"]
    else:
        maxtime = 60
        config["maxtime"] = maxtime
    if 'pointer' in config:
        pointer = config["pointer"]
    else:
        pointer = [''] + [1] * 9
        config["pointer"] = pointer
    if 'move' in config:
        move = config["move"]
    else:
        config["move"] = []
    if 'bookmark' in config:
        bookmark = config["bookmark"]
    else:
        bookmark = {}
        config["bookmark"] = bookmark
    config.write()
    return config
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import re
import time
import hashlib
import logging
import os
import json
import _thread
import sys
import shutil
from peewee import peewee
from . import updater
import pprint

########
VER_MAJOR = "2"
VER_MINOR = "0"
VER_STS = " Alpha"
VER_CODENAME = "Gizkard"
VER_STRING = "%s.%s%s (%s)" % (VER_MAJOR, VER_MINOR, VER_STS, VER_CODENAME)
#######

_rfc_1459_command_regexp = re.compile("^(:(?P<prefix>[^ ]+) +)?" +
    "(?P<command>[^ ]+)( *(?P<argument> .+))?")

database = peewee.SqliteDatabase('db/cobot.db', threadlocals=True)

class BaseModel(peewee.Model):
    class Meta:
        database = database

from .tables import User, UserPriv

try:
    User.create_table()
    UserPriv.create_table()
except:
    pass

class pyCoBot:
    def __init__(self, server, client, conf, mconf, sid):
        # zona de millones de definiciones de variables que se usan y no se usan
        self.sid = sid  # server id aka: el lugar que ocupa en el array de conf.
        self.botcli = client
        try:
            self.botcli.bots
        except:
            self.botcli.bots = []
        self.botcli.bots.append(self)
        self.handlers = []
        self.timehandlers = []
        self.mconf = mconf
        self.server = client.server()
        self.conf = conf
        self.modules = {}
        self.modinfo = {}
        self.modname = {}
        self.commandhandlers = {}

        self.authd = {}  # Usuarios autenticados..
        self.server.addhandler("pubmsg", self._cproc)
        self.server.addhandler("privmsg", self._cproc)
        self.server.addhandler("welcome", self._joinchans)
        for i, val in enumerate(conf['modules']):
            self.loadmod(conf['modules'][i], conf['server'])

        try:
            self.server.connect(server, conf['port'], conf['nick'],
                conf['nick'], "CoBot/" + VER_STRING)
        except:
            pass  # :P

    def _cproc(self, con, ev):
        p1 = re.compile("^" + re.escape(self.conf['prefix']) +
            "(\S{1,52})[ ]?(.*)", re.IGNORECASE)
        m1 = p1.search(ev.arguments[0])

        # Buscamos por el nick como prefijo..
        p2 = re.compile("^" + re.escape(self.conf['nick']) +
            "[:, ]? (\S{1,52})[ ]?(.*)", re.IGNORECASE)
        m2 = p2.search(ev.arguments[0])
        if not m1 is None:
            del ev.splitd[0]
            com = m1.group(1)
        elif not m2 is None:
            del ev.splitd[0]
            del ev.splitd[0]
            com = m2.group(1)

        if not m1 is None or not m2 is None:
            if com == "help" or com == "ayuda":
                r = False
                if not len(ev.splitd) > 0:
                    comlist = "help auth "
                    for i in list(self.commandhandlers.keys()):
                        if self.authchk(ev.source, self.commandhandlers[i]
                         ['cpriv'], self.modname[self.commandhandlers[i]
                         ['mod']], ev.target) is True and self. \
                         commandhandlers[i]['alias'] == i:
                            comlist = comlist + i + " "

                    con.privmsg(ev.target, "\2pyCoBot alpha\2. Comandos " +
                    "empezar con \2" + self.conf["prefix"] + "\2. " +
                    "Escriba " + self.conf["prefix"] + "help \2<comando>" +
                    "\2 para mas información sobre un comando")

                    con.privmsg(ev.target, "Comandos: " + comlist)
                else:
                    if ev.splitd[0] == "help":  # Harcoded help :P
                        r = "Muestra la ayuda de un comando, o, si no " + \
                         " tiene parametros, la lista de comandos." + \
                         " Sintaxis: help [comando]"
                    elif ev.splitd[0] == "auth":
                        r = "Identifica a un usuario registrado con el " + \
                         " Bot." + "Sintaxis: auth <usuario> <contraseña>" \
                         ". Este comando debe usarse vía mensaje privado."
                    else:
                        pprint.pprint(self.commandhandlers[ev.splitd[0]])
                        try:
                            r = self.commandhandlers[ev.splitd[0]]['chelp']
                            if not self.commandhandlers[ev.splitd[0]][
                            'alias'] != ev.splitd[0]:
                                r = "Alias de " + self.commandhandlers[ev.
                                splitd[0]]['alias'] + " " + r

                        except KeyError:
                            pass
                    if not r:
                        con.privmsg(ev.target, "No se ha encontrado el " +
                         "comando")
                    else:
                        con.privmsg(ev.target, "Ayuda de \2" + ev.splitd[0]
                         + "\2: " + r)
            elif com == "auth" and ev.type == "privmsg":
                self.auth(ev)
            elif com == "update":
                # >:D
                _thread.start_new_thread(self.updater, (self.server, ev))
            else:
                try:
                    self.commandhandlers[com]
                except KeyError:
                    return 0
                # Verificación de autenticación
                ocom = self.commandhandlers[com]['alias']
                if self.commandhandlers[com]['privmsgonly'] is True and \
                 ev.type == "pubmsg":
                    return 0
                try:
                    c = getattr(self.commandhandlers
                     [com]['mod'], ocom + "_p")(self,
                     self.server, ev)
                except AttributeError:
                    c = ev.target
                authd = self.authchk(ev.source, self.commandhandlers[com]
                ['cpriv'], self.modname[self.commandhandlers[com]['mod']],
                c)

                if authd is True:
                    getattr(self.commandhandlers[com]['mod'], ocom)(self,
                     self.server, ev)
                else:
                    self.server.privmsg(ev.target, "\00304Error\003: No a" +
                    "utorizado")

        #if ev.type == "welcome":
        #    import pprint
        #    pprint.pprint(self.conf)
        #    for i, val in enumerate(self.conf['autojoin']):
        #        con.join(self.conf['autojoin'][i])
        #elif ev.type == "ping":
        #    con.pong(ev.target)
        #elif ev.type == "ctcp":
        #    if ev.arguments[0] == "VERSION":
        #        con.ctcp_reply(ev.source, "VERSION CoBot/%s" % VER_STRING)
        #    elif ev.arguments[0] == "PING":
        #        con.ctcp_reply(ev.source, "PING " + ev.arguments[1])

    def _joinchans(self, con, ev):
        for i, val in enumerate(self.conf['autojoin']):
            con.join(self.conf['autojoin'][i])

    def authchk(self, host, cpriv, modsec, chan=False):
        # Verificación de autenticación
        if not cpriv == -1:
            try:
                uid = self.authd[host]
                continua = False
                for row in UserPriv.select().where(UserPriv.uid == uid):
                    if (row.priv >= cpriv) and (row.secmod == "*" or row.secmod
                     == modsec):
                        if chan is False and row.secchan == "*":
                            continua = True
                        else:
                            if row.secchan == "*" or row.secchan == chan:
                                continua = True
            except KeyError:
                return False
            if not continua is True:
                return False
            else:
                return True
        else:
            return True

    def is_identified(self, host):
        # Verificación de autenticación
		try:
			uid = self.authd[host]
			continua = False
			user = UserPriv.select().where(UserPriv.uid == uid):
			return user[0].nick
		except KeyError:
			return False

    def updater(self, cli, event):
        upd = updater.pyCoUpdater(cli, event, self.mconf, self)
        folder = "modules"
        for the_file in os.listdir(folder):
            #file_path = os.path.join(folder, the_file)
            try:
                f = open('modules/%s/%s.json' % (the_file, the_file))
                j = json.load(f)
                upd.addfile(j['type'], the_file, user=j['user'], repo=j['repo'],
                 url=j['url'])
            except IOError:
                pass
        if upd.update() is True:
            self.restart_program("[UPDATE] Aplicando actualizaciones")

    def auth(self, event):
        #session = self.session()
        passw = hashlib.sha1(event.splitd[1].encode('utf-8')).hexdigest()
        u = User.select().where(User.name == event.splitd[0].lower())
        try:
            if u[0].password == passw:
                self.authd[event.source] = u[0].uid
                self.server.privmsg(event.target, "Autenticado exitosamente")
        except:
            self.server.privmsg(event.target, "\00304Error\003: Usuario o " +
            "contraseña incorrectos")

    # Procesa timehandlers (función interna)
    def timehandler(self, hid, tme, c, f):
        while self.timehandlers[hid][0] is True:
            time.sleep(tme)
            getattr(c, f)(self, self.server)

    # Añade un timehandler. Parametros: intervalo en segundos, modulo, funcion
    def addTimeHandler(self, interval, module, func):
        self.timehandlers.append([True, module])
        _thread.start_new_thread(self.timehandler, (len(self.timehandlers) - 1,
            interval, module, func))

    def addHandler(self, numeric, modulo, func):
        """ Registra un handler con el bot.
        Parametros:
            - server: Nombre (dirección) del servidor en el que se registra el
             handler (la misma que aparece en la configuración)
            - numeric: Nombre del comando IRC que accionara el handler
              (lista: irc/events.py)
            - modulo: 'self' del módulo en el que se registra el handler
            - func: la función que se llamará en el módulo en cuestión
        """
        h = {}
        h['numeric'] = numeric
        h['mod'] = modulo
        h['func'] = func
        h['id'] = self.server.addhandler(numeric, getattr(modulo, func))
        self.handlers.append(h)

        logging.debug("Registrado handler en '%s' ('%s')"
           % (self.conf['server'], numeric))

    def addCommandHandler(self, command, module, chelp="", cpriv=-1,
         cprivchan=False, privmsgonly=False, alias=[]):
        """ Registra un commandHandler con el bot (un comando, bah)
        Parametros:
            - command: Nombre del comando que se va a registrar
            - module: 'self' del módulo donde se registra el handler
            - chelp: La ayuda del comando
            - cpriv: Privilegios requeridos para usar el comando
            - privmsgonly: si el comando solo debe ser ejecutado por privmsg
            - cprivchan: si se aplicarán privilegios por canal.
        Los comandos se accionan al escribir <prefijo>comando;
         <nickdelbot>, comando; <nickdelbot>: comando y <nickdelbot> comando """
        h = {}
        h['mod'] = module
        h['cpriv'] = cpriv
        h['cprivchan'] = cprivchan
        h['privmsgonly'] = privmsgonly
        h['chelp'] = chelp
        h['alias'] = command
        self.commandhandlers[command] = h
        for i, val in enumerate(alias):
            self.commandhandlers[val] = h

        logging.debug("Registrado commandHandler en '%s' ('%s')"
         % (self.conf['server'], command))

    # Retorna true si "module" está cargado
    def is_loaded(self, module):
        try:
            self.modinfo[module]
            return True
        except KeyError:
            return False

    # Retorna un objeto de "module", o si no está cargado, False
    def getmodule(self, module):
        if self.is_loaded(module) is True:
            return self.modules[module]
        else:
            return False

    # carga de modulos
    def loadmod(self, module, cli):
        logging.info('Cargando modulo "%s" en %s'
         % (module, self.conf['server']))
        try:
            self.modinfo[module]
            logging.warning("Se ha intentado cargar un módulo que ya estaba"
             "cargado!!")
            return 3
        except KeyError:
            pass
        try:
            nclassname = "m" + str(int(time.time())) + "x" + module
            shutil.copytree("modules/%s/" % module, "tmp/%s/%s" % (self.conf
             ['pserver'], nclassname))
            touch("tmp/%s/%s/__init__.py" % (self.conf['pserver'], nclassname))
            try:
                self.modules[module] = my_import("tmp." + self.conf['pserver'] +
                "." + nclassname + "." + module + "." + module)(self,
                 self.server)
            except AttributeError as q:
                if str(q) == "'module' object has no attribute '" + module + \
                    "'":
                    logging.error("No se pudo cargar el modulo '%s'. No se ha" %
                     module + " encontrado la clase principal.")
                else:
                    logging.error("No se ha podido cargar el módulo '%s'"
                        " debido a algun error interno en su __init__: %s" % (
                        module, q))
                return 2
            self.modinfo[module] = nclassname
            self.modname[self.modules[module]] = module
        except IOError:
            logging.error("No se pudo cargar el modulo '%s'. No se ha" %
             module + " encontrado el archivo.")
            return 1

    def unloadmod(self, module):
        logging.info('Des-cargando modulo "%s" en %s'
         % (module, self.conf['server']))
        try:
            self.modules[module]
        except KeyError:
            logging.error("El modulo %s no existe o no esta cargado" % module)
            return 1
        shutil.rmtree("tmp/%s/%s" % (self.conf['pserver'], self.modinfo
         [module]))
        del self.modinfo[module]
        # Eliminamos los handlers..
        for i, val in enumerate(self.handlers):
            if self.modules[module] == self.handlers[i]['mod']:
                logging.debug('Eliminando handler "%s" del modulo %s en %s'
                 % (self.handlers[i]['numeric'], module, self.conf['server']))
                self.server.delhandler(self.handlers[i]['id'])
                del self.handlers[i]

        l = []
        # Eliminamos los commandhandlers
        for i in list(self.commandhandlers.keys()):
            if self.modules[module] == self.commandhandlers[i]['mod']:
                l.append(i)
        for q in enumerate(l):
                logging.debug('Eliminando commandhandler "%s" del modulo %s'
                 % (q[1], module))
                del self.commandhandlers[q[1]]
        # Matamos a los timehandlers..
        for k, i in enumerate(self.timehandlers):
            if i[1] == self.modules[module]:
                self.timehandlers[k][0] = False

    def restart_program(self, quitmsg):
        for i in enumerate(self.botcli.boservers):
            try:
                i[1].server.quit(quitmsg)
            except:
                pass  # guh..
        python = sys.executable
        os.execl(python, python, * sys.argv)

def my_import(cl):
        d = cl.rfind(".")
        classname = cl[d + 1:len(cl)]
        m = __import__(cl[0:d], globals(), locals(), [classname])
        return getattr(m, classname)

def touch(fname):
    if os.path.exists(fname):
        os.utime(fname, None)
    else:
        open(fname, 'w').close()
<commit_msg>Ups..<commit_after># -*- coding: utf-8 -*-
import re
import time
import hashlib
import logging
import os
import json
import _thread
import sys
import shutil
from peewee import peewee
from . import updater
import pprint

########
VER_MAJOR = "2"
VER_MINOR = "0"
VER_STS = " Alpha"
VER_CODENAME = "Gizkard"
VER_STRING = "%s.%s%s (%s)" % (VER_MAJOR, VER_MINOR, VER_STS, VER_CODENAME)
#######

_rfc_1459_command_regexp = re.compile("^(:(?P<prefix>[^ ]+) +)?" +
    "(?P<command>[^ ]+)( *(?P<argument> .+))?")

database = peewee.SqliteDatabase('db/cobot.db', threadlocals=True)

class BaseModel(peewee.Model):
    class Meta:
        database = database

from .tables import User, UserPriv

try:
    User.create_table()
    UserPriv.create_table()
except:
    pass

class pyCoBot:
    def __init__(self, server, client, conf, mconf, sid):
        # zona de millones de definiciones de variables que se usan y no se usan
        self.sid = sid  # server id aka: el lugar que ocupa en el array de conf.
        self.botcli = client
        try:
            self.botcli.bots
        except:
            self.botcli.bots = []
        self.botcli.bots.append(self)
        self.handlers = []
        self.timehandlers = []
        self.mconf = mconf
        self.server = client.server()
        self.conf = conf
        self.modules = {}
        self.modinfo = {}
        self.modname = {}
        self.commandhandlers = {}

        self.authd = {}  # Usuarios autenticados..
        self.server.addhandler("pubmsg", self._cproc)
        self.server.addhandler("privmsg", self._cproc)
        self.server.addhandler("welcome", self._joinchans)
        for i, val in enumerate(conf['modules']):
            self.loadmod(conf['modules'][i], conf['server'])

        try:
            self.server.connect(server, conf['port'], conf['nick'],
                conf['nick'], "CoBot/" + VER_STRING)
        except:
            pass  # :P

    def _cproc(self, con, ev):
        p1 = re.compile("^" + re.escape(self.conf['prefix']) +
            "(\S{1,52})[ ]?(.*)", re.IGNORECASE)
        m1 = p1.search(ev.arguments[0])

        # Buscamos por el nick como prefijo..
        p2 = re.compile("^" + re.escape(self.conf['nick']) +
            "[:, ]? (\S{1,52})[ ]?(.*)", re.IGNORECASE)
        m2 = p2.search(ev.arguments[0])
        if not m1 is None:
            del ev.splitd[0]
            com = m1.group(1)
        elif not m2 is None:
            del ev.splitd[0]
            del ev.splitd[0]
            com = m2.group(1)

        if not m1 is None or not m2 is None:
            if com == "help" or com == "ayuda":
                r = False
                if not len(ev.splitd) > 0:
                    comlist = "help auth "
                    for i in list(self.commandhandlers.keys()):
                        if self.authchk(ev.source, self.commandhandlers[i]
                         ['cpriv'], self.modname[self.commandhandlers[i]
                         ['mod']], ev.target) is True and self. \
                         commandhandlers[i]['alias'] == i:
                            comlist = comlist + i + " "

                    con.privmsg(ev.target, "\2pyCoBot alpha\2. Comandos " +
                    "empezar con \2" + self.conf["prefix"] + "\2. " +
                    "Escriba " + self.conf["prefix"] + "help \2<comando>" +
                    "\2 para mas información sobre un comando")

                    con.privmsg(ev.target, "Comandos: " + comlist)
                else:
                    if ev.splitd[0] == "help":  # Harcoded help :P
                        r = "Muestra la ayuda de un comando, o, si no " + \
                         " tiene parametros, la lista de comandos." + \
                         " Sintaxis: help [comando]"
                    elif ev.splitd[0] == "auth":
                        r = "Identifica a un usuario registrado con el " + \
                         " Bot." + "Sintaxis: auth <usuario> <contraseña>" \
                         ". Este comando debe usarse vía mensaje privado."
                    else:
                        pprint.pprint(self.commandhandlers[ev.splitd[0]])
                        try:
                            r = self.commandhandlers[ev.splitd[0]]['chelp']
                            if not self.commandhandlers[ev.splitd[0]][
                            'alias'] != ev.splitd[0]:
                                r = "Alias de " + self.commandhandlers[ev.
                                splitd[0]]['alias'] + " " + r

                        except KeyError:
                            pass
                    if not r:
                        con.privmsg(ev.target, "No se ha encontrado el " +
                         "comando")
                    else:
                        con.privmsg(ev.target, "Ayuda de \2" + ev.splitd[0]
                         + "\2: " + r)
            elif com == "auth" and ev.type == "privmsg":
                self.auth(ev)
            elif com == "update":
                # >:D
                _thread.start_new_thread(self.updater, (self.server, ev))
            else:
                try:
                    self.commandhandlers[com]
                except KeyError:
                    return 0
                # Verificación de autenticación
                ocom = self.commandhandlers[com]['alias']
                if self.commandhandlers[com]['privmsgonly'] is True and \
                 ev.type == "pubmsg":
                    return 0
                try:
                    c = getattr(self.commandhandlers
                     [com]['mod'], ocom + "_p")(self,
                     self.server, ev)
                except AttributeError:
                    c = ev.target
                authd = self.authchk(ev.source, self.commandhandlers[com]
                ['cpriv'], self.modname[self.commandhandlers[com]['mod']],
                c)

                if authd is True:
                    getattr(self.commandhandlers[com]['mod'], ocom)(self,
                     self.server, ev)
                else:
                    self.server.privmsg(ev.target, "\00304Error\003: No a" +
                    "utorizado")

        #if ev.type == "welcome":
        #    import pprint
        #    pprint.pprint(self.conf)
        #    for i, val in enumerate(self.conf['autojoin']):
        #        con.join(self.conf['autojoin'][i])
        #elif ev.type == "ping":
        #    con.pong(ev.target)
        #elif ev.type == "ctcp":
        #    if ev.arguments[0] == "VERSION":
        #        con.ctcp_reply(ev.source, "VERSION CoBot/%s" % VER_STRING)
        #    elif ev.arguments[0] == "PING":
        #        con.ctcp_reply(ev.source, "PING " + ev.arguments[1])

    def _joinchans(self, con, ev):
        for i, val in enumerate(self.conf['autojoin']):
            con.join(self.conf['autojoin'][i])

    def authchk(self, host, cpriv, modsec, chan=False):
        # Verificación de autenticación
        if not cpriv == -1:
            try:
                uid = self.authd[host]
                continua = False
                for row in UserPriv.select().where(UserPriv.uid == uid):
                    if (row.priv >= cpriv) and (row.secmod == "*" or row.secmod
                     == modsec):
                        if chan is False and row.secchan == "*":
                            continua = True
                        else:
                            if row.secchan == "*" or row.secchan == chan:
                                continua = True
            except KeyError:
                return False
            if not continua is True:
                return False
            else:
                return True
        else:
            return True

    def is_identified(self, host):
        # Verificación de autenticación
		try:
			uid = self.authd[host]
			continua = False
			user = UserPriv.select().where(UserPriv.uid == uid):
			return user[0].name
		except KeyError:
			return False

    def updater(self, cli, event):
        upd = updater.pyCoUpdater(cli, event, self.mconf, self)
        folder = "modules"
        for the_file in os.listdir(folder):
            #file_path = os.path.join(folder, the_file)
            try:
                f = open('modules/%s/%s.json' % (the_file, the_file))
                j = json.load(f)
                upd.addfile(j['type'], the_file, user=j['user'], repo=j['repo'],
                 url=j['url'])
            except IOError:
                pass
        if upd.update() is True:
            self.restart_program("[UPDATE] Aplicando actualizaciones")

    def auth(self, event):
        #session = self.session()
        passw = hashlib.sha1(event.splitd[1].encode('utf-8')).hexdigest()
        u = User.select().where(User.name == event.splitd[0].lower())
        try:
            if u[0].password == passw:
                self.authd[event.source] = u[0].uid
                self.server.privmsg(event.target, "Autenticado exitosamente")
        except:
            self.server.privmsg(event.target, "\00304Error\003: Usuario o " +
            "contraseña incorrectos")

    # Procesa timehandlers (función interna)
    def timehandler(self, hid, tme, c, f):
        while self.timehandlers[hid][0] is True:
            time.sleep(tme)
            getattr(c, f)(self, self.server)

    # Añade un timehandler. Parametros: intervalo en segundos, modulo, funcion
    def addTimeHandler(self, interval, module, func):
        self.timehandlers.append([True, module])
        _thread.start_new_thread(self.timehandler, (len(self.timehandlers) - 1,
            interval, module, func))

    def addHandler(self, numeric, modulo, func):
        """ Registra un handler con el bot.
        Parametros:
            - server: Nombre (dirección) del servidor en el que se registra el
             handler (la misma que aparece en la configuración)
            - numeric: Nombre del comando IRC que accionara el handler
              (lista: irc/events.py)
            - modulo: 'self' del módulo en el que se registra el handler
            - func: la función que se llamará en el módulo en cuestión
        """
        h = {}
        h['numeric'] = numeric
        h['mod'] = modulo
        h['func'] = func
        h['id'] = self.server.addhandler(numeric, getattr(modulo, func))
        self.handlers.append(h)

        logging.debug("Registrado handler en '%s' ('%s')"
           % (self.conf['server'], numeric))

    def addCommandHandler(self, command, module, chelp="", cpriv=-1,
         cprivchan=False, privmsgonly=False, alias=[]):
        """ Registra un commandHandler con el bot (un comando, bah)
        Parametros:
            - command: Nombre del comando que se va a registrar
            - module: 'self' del módulo donde se registra el handler
            - chelp: La ayuda del comando
            - cpriv: Privilegios requeridos para usar el comando
            - privmsgonly: si el comando solo debe ser ejecutado por privmsg
            - cprivchan: si se aplicarán privilegios por canal.
        Los comandos se accionan al escribir <prefijo>comando;
         <nickdelbot>, comando; <nickdelbot>: comando y <nickdelbot> comando """
        h = {}
        h['mod'] = module
        h['cpriv'] = cpriv
        h['cprivchan'] = cprivchan
        h['privmsgonly'] = privmsgonly
        h['chelp'] = chelp
        h['alias'] = command
        self.commandhandlers[command] = h
        for i, val in enumerate(alias):
            self.commandhandlers[val] = h

        logging.debug("Registrado commandHandler en '%s' ('%s')"
         % (self.conf['server'], command))

    # Retorna true si "module" está cargado
    def is_loaded(self, module):
        try:
            self.modinfo[module]
            return True
        except KeyError:
            return False

    # Retorna un objeto de "module", o si no está cargado, False
    def getmodule(self, module):
        if self.is_loaded(module) is True:
            return self.modules[module]
        else:
            return False

    # carga de modulos
    def loadmod(self, module, cli):
        logging.info('Cargando modulo "%s" en %s'
         % (module, self.conf['server']))
        try:
            self.modinfo[module]
            logging.warning("Se ha intentado cargar un módulo que ya estaba"
             "cargado!!")
            return 3
        except KeyError:
            pass
        try:
            nclassname = "m" + str(int(time.time())) + "x" + module
            shutil.copytree("modules/%s/" % module, "tmp/%s/%s" % (self.conf
             ['pserver'], nclassname))
            touch("tmp/%s/%s/__init__.py" % (self.conf['pserver'], nclassname))
            try:
                self.modules[module] = my_import("tmp." + self.conf['pserver'] +
                "." + nclassname + "." + module + "." + module)(self,
                 self.server)
            except AttributeError as q:
                if str(q) == "'module' object has no attribute '" + module + \
                    "'":
                    logging.error("No se pudo cargar el modulo '%s'. No se ha" %
                     module + " encontrado la clase principal.")
                else:
                    logging.error("No se ha podido cargar el módulo '%s'"
                        " debido a algun error interno en su __init__: %s" % (
                        module, q))
                return 2
            self.modinfo[module] = nclassname
            self.modname[self.modules[module]] = module
        except IOError:
            logging.error("No se pudo cargar el modulo '%s'. No se ha" %
             module + " encontrado el archivo.")
            return 1

    def unloadmod(self, module):
        logging.info('Des-cargando modulo "%s" en %s'
         % (module, self.conf['server']))
        try:
            self.modules[module]
        except KeyError:
            logging.error("El modulo %s no existe o no esta cargado" % module)
            return 1
        shutil.rmtree("tmp/%s/%s" % (self.conf['pserver'], self.modinfo
         [module]))
        del self.modinfo[module]
        # Eliminamos los handlers..
        for i, val in enumerate(self.handlers):
            if self.modules[module] == self.handlers[i]['mod']:
                logging.debug('Eliminando handler "%s" del modulo %s en %s'
                 % (self.handlers[i]['numeric'], module, self.conf['server']))
                self.server.delhandler(self.handlers[i]['id'])
                del self.handlers[i]

        l = []
        # Eliminamos los commandhandlers
        for i in list(self.commandhandlers.keys()):
            if self.modules[module] == self.commandhandlers[i]['mod']:
                l.append(i)
        for q in enumerate(l):
                logging.debug('Eliminando commandhandler "%s" del modulo %s'
                 % (q[1], module))
                del self.commandhandlers[q[1]]
        # Matamos a los timehandlers..
        for k, i in enumerate(self.timehandlers):
            if i[1] == self.modules[module]:
                self.timehandlers[k][0] = False

    def restart_program(self, quitmsg):
        for i in enumerate(self.botcli.boservers):
            try:
                i[1].server.quit(quitmsg)
            except:
                pass  # guh..
        python = sys.executable
        os.execl(python, python, * sys.argv)

def my_import(cl):
        d = cl.rfind(".")
        classname = cl[d + 1:len(cl)]
        m = __import__(cl[0:d], globals(), locals(), [classname])
        return getattr(m, classname)

def touch(fname):
    if os.path.exists(fname):
        os.utime(fname, None)
    else:
        open(fname, 'w').close()
<|endoftext|>


<commit_before># Copyright 2010-2011 OpenStack LLC.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

"""
Cloud Keep version
"""

__version__ = '0.1.11'
__version_info__ = tuple(__version__.split('0.1.11'))
<commit_msg>Prepare for next release<commit_after># Copyright 2010-2011 OpenStack LLC.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

"""
Cloud Keep version
"""

__version__ = '0.1.12dev'
__version_info__ = tuple(__version__.split('0.1.12dev'))
<|endoftext|>


<commit_before>#! /usr/bin/env python
# Licensed to Cloudera, Inc. under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  Cloudera, Inc. licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from setuptools import setup, find_packages

from sys import version_info, platform

if version_info[:2] > (2, 5):
    install_requires = []
else:
    install_requires = ['simplejson >= 2.0.0']

# Python 2.6 and below requires argparse
if version_info[:2] < (2, 7):
    install_requires += ['argparse']

# Mac does not come default with readline, this is needed for autocomplete
# in the cmps shell
if platform == 'darwin':
    install_requires += ['readline']

setup(
  name = 'cm_api',
  version = '6.0.0',    # Compatible with API v6
  packages = find_packages('src', exclude=['cm_api_tests']),
  package_dir = {'cm_api': 'src/cm_api',
                 'cm_shell': 'src/cm_shell'},

  # Project uses simplejson, so ensure that it gets installed or upgraded
  # on the target machine
  install_requires = install_requires,

  author = 'Cloudera, Inc.',
  author_email = 'scm-users@cloudera.org',
  description = 'Cloudera Manager API client',
  long_desc = 'cm_api is a Python client to the Cloudera Manager REST API',
  license = 'Apache License 2.0',
  url = 'http://cloudera.github.com/cm_api/',
  classifiers = [
        "Development Status :: 5 - Production/Stable",
        "Operating System :: OS Independent",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2.6",
        "Programming Language :: Python :: 2.7",
  ],
  entry_points = { 'console_scripts': [ 'cmps = cm_shell.cmps:main', ]}
)
<commit_msg>[py] Update package metadata to CM 5 beta2<commit_after>#! /usr/bin/env python
# Licensed to Cloudera, Inc. under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  Cloudera, Inc. licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from setuptools import setup, find_packages

from sys import version_info, platform

if version_info[:2] > (2, 5):
    install_requires = []
else:
    install_requires = ['simplejson >= 2.0.0']

# Python 2.6 and below requires argparse
if version_info[:2] < (2, 7):
    install_requires += ['argparse']

# Mac does not come default with readline, this is needed for autocomplete
# in the cmps shell
if platform == 'darwin':
    install_requires += ['readline']

setup(
  name = 'cm_api',
  version = '6.0.1',    # Compatible with API v6 (CM 5.0 beta 2)
  packages = find_packages('src', exclude=['cm_api_tests']),
  package_dir = {'cm_api': 'src/cm_api',
                 'cm_shell': 'src/cm_shell'},

  # Project uses simplejson, so ensure that it gets installed or upgraded
  # on the target machine
  install_requires = install_requires,

  author = 'Cloudera, Inc.',
  author_email = 'scm-users@cloudera.org',
  description = 'Cloudera Manager API client',
  long_desc = 'cm_api is a Python client to the Cloudera Manager REST API',
  license = 'Apache License 2.0',
  url = 'http://cloudera.github.com/cm_api/',
  classifiers = [
        "Development Status :: 5 - Production/Stable",
        "Operating System :: OS Independent",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2.6",
        "Programming Language :: Python :: 2.7",
  ],
  entry_points = { 'console_scripts': [ 'cmps = cm_shell.cmps:main', ]}
)
<|endoftext|>


<commit_before>"""Define project metadata
"""

__all__ = [
    '__title__',
    '__summary__',
    '__url__',
    '__version__',
    '__author__',
    '__email__',
    '__license__',
]

__title__ = 'pydash'
__summary__ = 'Python port of Lo-Dash'
__url__ = 'https://github.com/dgilland/pydash'

__version__ = '1.1.0'

__author__ = 'Derrick Gilland'
__email__ = 'dgilland@gmail.com'

__license__ = 'MIT License'
<commit_msg>Add v2 dev version designation.<commit_after>"""Define project metadata
"""

__all__ = [
    '__title__',
    '__summary__',
    '__url__',
    '__version__',
    '__author__',
    '__email__',
    '__license__',
]

__title__ = 'pydash'
__summary__ = 'Python port of Lo-Dash'
__url__ = 'https://github.com/dgilland/pydash'

__version__ = '2.0.0-dev'

__author__ = 'Derrick Gilland'
__email__ = 'dgilland@gmail.com'

__license__ = 'MIT License'
<|endoftext|>