<commit_before>import os
from collections import defaultdict
from collections import Iterable
import logging
from ..readers import DatasetReader
from ..writers import DatasetWriter
from ..errors import DataError

logger = logging.getLogger(__name__)

def combine_datasets(input_files, output_file, delete_input_files=False):
    '''
    Combine data stored across several HDF5 files into one HDF5 file.

    Parameters
    ----------
    input_files: List[str]
        paths to Jterator data files that were generated by individual jobs
    output_file: str
        path to the final data file that should contain the entire datasets
    delete_input_files: bool, optional
        whether `input_files` should be deleted after their content is fused
        into `output_file` (default: ``False``)

    Returns
    -------
    Dict[str, pandas.core.frame.DataFrame or numpy.ndarray]
        fused datasets for each dataset; the key specifies the full path to the
        location of the dataset within the HDF5 file
    '''

    # Get paths to datasets in the file recursively
    # NOTE: This approach is not general, but rather assumes a defined structure
    logger.info('determine names and data types of the final datasets')
    # n_features = defaultdict(int)
    datasets = defaultdict()
    with DatasetReader(input_files[0]) as f:

        metadata_datasets = f.list_datasets('/metadata')
        datasets['metadata'] = [
            {
                'path': '/metadata/%s' % d,
                'dtype': f.get_type('/metadata/%s' % d),
            }
            for d in metadata_datasets
        ]

        object_names = f.list_groups('/objects')
        for obj_name in object_names:
            datasets[obj_name] = defaultdict(list)
            features_path = 'objects/%s/features' % obj_name
            if f.exists(features_path):
                features_datasets = f.list_datasets(features_path)
                datasets[obj_name]['features'] = [
                    {
                        'path': '%s/%s' % (features_path, d),
                        'dtype': f.get_type('%s/%s' % (features_path, d))
                    }
                    for d in features_datasets
                ]
                # if features_datasets:
                #     dims = f.get_dimensions(datasets[obj_name]['features'][0])
                #     if len(dims) > 1:
                #         n_features[obj_name] = dims[1]
                #     elif len(dims) == 1:
                #         n_features[obj_name] = 1
                #     else:
                #         n_features[obj_name] = None
                # else:
                #     n_features[obj_name] = None

            segmentation_path = 'objects/%s/segmentation' % obj_name
            if f.exists(segmentation_path):
                segmentation_datasets = f.list_datasets(segmentation_path)
                datasets[obj_name]['segmentation'] = [
                    {
                        'path': '%s/%s' % (segmentation_path, d),
                        'dtype': f.get_type('%s/%s' % (segmentation_path, d))
                    }
                    for d in segmentation_datasets
                ]
                segmentation_subpaths = [
                    '%s/%s' % (segmentation_path, p)
                    for p in f.list_groups(segmentation_path)
                ]
                for path in segmentation_subpaths:
                    segmentation_datasets = f.list_datasets(path)
                    datasets[obj_name]['segmentation'].extend(
                        {
                            'path': '%s/%s' % (path, d),
                            'dtype': f.get_type('%s/%s' % (path, d))
                        }
                        for d in segmentation_datasets
                    )

    # Determine the dimensions of the final datasets,
    # i.e. the number of objects that were identified in each image
    # and the number of features that were measure per object.
    # The "metadata" datasets are simply scalars, all other datasets
    # have the same number of rows, which corresponds to the number of objects.
    logger.info('determine dimensions of the final datasets')
    n_jobs = len(input_files)
    n_objects = defaultdict(int)
    for i, filename in enumerate(input_files):

        with DatasetReader(filename) as f:

            for obj_name in object_names:
                features_path = 'objects/%s/features' % obj_name
                segmentation_path = 'objects/%s/segmentation' % obj_name
                if f.exists(features_path):
                    dims = f.get_dimensions(datasets[obj_name]['features'][0])
                elif f.exists(segmentation_path):
                    obj_ids_path = '%s/object_ids' % segmentation_path
                    dims = f.get_dimensions(obj_ids_path)
                else:
                    raise DataError('Features or segmentation data must exist.')
                n_objects[obj_name] += dims[0]

    # Create datasets on disk
    logger.info('preallocate final datasets')
    with DatasetWriter(output_file, 'w') as out:

        for d in datasets['metadata']:
            d.update({'dims': (n_jobs, )})
            out.preallocate(**d)

        for obj_name in object_names:
            for d in datasets[obj_name]['segmentation']:
                d.update({'dims': (n_objects[obj_name], )})
                out.preallocate(**d)
            for d in datasets[obj_name]['features']:
                d.update({'dims': (n_objects[obj_name], )})
                out.preallocate(**d)

    logger.info('load individual datasets and write them into final datasets')
    job_index_count = 0
    object_index_count = defaultdict(int)
    for obj_name in object_names:
        object_index_count[obj_name] = 0
    with DatasetWriter(output_file) as out:

        for i, filename in enumerate(input_files):

            logger.debug('process file: %s', filename)

            with DatasetReader(filename) as f:

                # Collect metadata per site, i.e. per job ID
                metadata_path = '/metadata'
                dataset_names = f.list_datasets(metadata_path)
                for name in dataset_names:
                    dataset_path = '{group}/{dataset}'.format(
                                        group=metadata_path,
                                        dataset=name)
                    data = f.read(dataset_path)
                    if len(data.shape) > 1:
                        raise DataError(
                                'Dataset must be one-dimensional: %s'
                                % dataset_path)
                    index = range(
                            job_index_count,
                            (1 + job_index_count)
                    )
                    out.write(dataset_path, data=data, index=index)
                job_index_count += 1

                # Collect features and segmentations per object
                for obj_name in object_names:
                    features_path = 'objects/%s/features' % obj_name
                    segmentation_path = 'objects/%s/segmentation' % obj_name

                    if f.exists(features_path):
                        dataset_names = f.list_datasets(features_path)
                        for name in dataset_names:
                            dataset_path = '{group}/{dataset}'.format(
                                            group=features_path,
                                            dataset=name)
                            data = f.read(dataset_path)
                            if len(data.shape) > 1:
                                raise DataError(
                                        'Dataset must be one-dimensional: %s'
                                        % dataset_path)
                            index = range(
                                    object_index_count[obj_name],
                                    (len(data) + object_index_count[obj_name])
                            )
                            out.write(dataset_path, data=data, index=index)

                    if f.exists(segmentation_path):
                        dataset_names = f.list_datasets(segmentation_path)
                        for name in dataset_names:
                            dataset_path = '{group}/{dataset}'.format(
                                            group=segmentation_path,
                                            dataset=name)
                            data = f.read(dataset_path)
                            if len(data.shape) > 1:
                                raise DataError(
                                        'Dataset must be one-dimensional: %s'
                                        % dataset_path)
                            index = range(
                                    object_index_count[obj_name],
                                    (len(data) + object_index_count[obj_name])
                            )
                            out.write(dataset_path, data=data, index=index)

                        group_names = f.list_groups(segmentation_path)
                        for g_name in group_names:
                            group_path = '{group}/{subgroup}'.format(
                                            group=segmentation_path,
                                            subgroup=g_name)
                            dataset_names = f.list_datasets(group_path)
                            for name in dataset_names:
                                dataset_path = '{group}/{dataset}'.format(
                                                group=group_path, dataset=name)
                                data = f.read(dataset_path)
                                if len(data.shape) > 1:
                                    raise DataError(
                                            'Dataset must be one-dimensional: %s'
                                            % dataset_path)
                                index = range(
                                        object_index_count[obj_name],
                                        (len(data) +
                                         object_index_count[obj_name])
                                )
                                out.write(dataset_path, data=data, index=index)

                    object_index_count[obj_name] += len(data)

            if delete_input_files:
                logger.debug('remove input file: %s', f)
                os.remove(filename)

def update_datasets(old_filename, new_filename):
    '''
    Recursively copy all datasets from one HDF5 file to a new HDF5 file without
    overwriting existing ones.

    Parameters
    ----------
    old_filename: str
        absolute path to the file whose content should be copied
    new_filename: str
        absolute path to the file, which should be updated
    '''
    with DatasetReader(old_filename) as old_file:
        with DatasetWriter(new_filename) as new_file:
            def copy_recursively(p):
                groups = old_file.list_groups(p)
                for g in groups:
                    group_path = '{group}/{subgroup}'.format(
                                    group=p, subgroup=g)
                    if g == 'coordinates':
                        # The coordinates for the visualization have to be
                        # recalculated in case the segmentation has changed.
                        continue
                    for d in old_file.list_datasets(group_path):
                        dataset_path = '{group}/{dataset}'.format(
                                            group=group_path, dataset=d)
                        if not new_file.exists(dataset_path):
                            # Keep the more recent dataset.
                            new_file.write(
                                    dataset_path,
                                    data=old_file.read(dataset_path))
                    copy_recursively(group_path)
            copy_recursively('/')
<commit_msg>Fix bug in data fusion<commit_after>import os
from collections import defaultdict
from collections import Iterable
import logging
from ..readers import DatasetReader
from ..writers import DatasetWriter
from ..errors import DataError

logger = logging.getLogger(__name__)

def combine_datasets(input_files, output_file, delete_input_files=False):
    '''
    Combine data stored across several HDF5 files into one HDF5 file.

    Parameters
    ----------
    input_files: List[str]
        paths to Jterator data files that were generated by individual jobs
    output_file: str
        path to the final data file that should contain the entire datasets
    delete_input_files: bool, optional
        whether `input_files` should be deleted after their content is fused
        into `output_file` (default: ``False``)

    Returns
    -------
    Dict[str, pandas.core.frame.DataFrame or numpy.ndarray]
        fused datasets for each dataset; the key specifies the full path to the
        location of the dataset within the HDF5 file
    '''

    # Get paths to datasets in the file recursively
    # NOTE: This approach is not general, but rather assumes a defined structure
    logger.info('determine names and data types of the final datasets')
    # n_features = defaultdict(int)
    datasets = defaultdict()
    with DatasetReader(input_files[0]) as f:

        metadata_datasets = f.list_datasets('/metadata')
        datasets['metadata'] = [
            {
                'path': '/metadata/%s' % d,
                'dtype': f.get_type('/metadata/%s' % d),
            }
            for d in metadata_datasets
        ]

        object_names = f.list_groups('/objects')
        for obj_name in object_names:
            datasets[obj_name] = defaultdict(list)
            features_path = 'objects/%s/features' % obj_name
            if f.exists(features_path):
                features_datasets = f.list_datasets(features_path)
                datasets[obj_name]['features'] = [
                    {
                        'path': '%s/%s' % (features_path, d),
                        'dtype': f.get_type('%s/%s' % (features_path, d))
                    }
                    for d in features_datasets
                ]
                # if features_datasets:
                #     dims = f.get_dimensions(datasets[obj_name]['features'][0])
                #     if len(dims) > 1:
                #         n_features[obj_name] = dims[1]
                #     elif len(dims) == 1:
                #         n_features[obj_name] = 1
                #     else:
                #         n_features[obj_name] = None
                # else:
                #     n_features[obj_name] = None

            segmentation_path = 'objects/%s/segmentation' % obj_name
            if f.exists(segmentation_path):
                segmentation_datasets = f.list_datasets(segmentation_path)
                datasets[obj_name]['segmentation'] = [
                    {
                        'path': '%s/%s' % (segmentation_path, d),
                        'dtype': f.get_type('%s/%s' % (segmentation_path, d))
                    }
                    for d in segmentation_datasets
                ]
                segmentation_subpaths = [
                    '%s/%s' % (segmentation_path, p)
                    for p in f.list_groups(segmentation_path)
                ]
                for path in segmentation_subpaths:
                    segmentation_datasets = f.list_datasets(path)
                    datasets[obj_name]['segmentation'].extend(
                        {
                            'path': '%s/%s' % (path, d),
                            'dtype': f.get_type('%s/%s' % (path, d))
                        }
                        for d in segmentation_datasets
                    )

    # Determine the dimensions of the final datasets,
    # i.e. the number of objects that were identified in each image
    # and the number of features that were measure per object.
    # The "metadata" datasets are simply scalars, all other datasets
    # have the same number of rows, which corresponds to the number of objects.
    logger.info('determine dimensions of the final datasets')
    n_jobs = len(input_files)
    n_objects = defaultdict(int)
    for i, filename in enumerate(input_files):

        with DatasetReader(filename) as f:

            for obj_name in object_names:
                features_path = 'objects/%s/features' % obj_name
                segmentation_path = 'objects/%s/segmentation' % obj_name
                if f.exists(features_path):
                    feat_path = datasets[obj_name]['features'][0]['path']
                    dims = f.get_dimensions(feat_path)
                elif f.exists(segmentation_path):
                    obj_ids_path = '%s/object_ids' % segmentation_path
                    dims = f.get_dimensions(obj_ids_path)
                else:
                    raise DataError('Features or segmentation data must exist.')
                n_objects[obj_name] += dims[0]

    # Create datasets on disk
    logger.info('preallocate final datasets')
    with DatasetWriter(output_file, 'w') as out:

        for d in datasets['metadata']:
            d.update({'dims': (n_jobs, )})
            out.preallocate(**d)

        for obj_name in object_names:
            for d in datasets[obj_name]['segmentation']:
                d.update({'dims': (n_objects[obj_name], )})
                out.preallocate(**d)
            for d in datasets[obj_name]['features']:
                d.update({'dims': (n_objects[obj_name], )})
                out.preallocate(**d)

    logger.info('load individual datasets and write them into final datasets')
    job_index_count = 0
    object_index_count = defaultdict(int)
    for obj_name in object_names:
        object_index_count[obj_name] = 0
    with DatasetWriter(output_file) as out:

        for i, filename in enumerate(input_files):

            logger.debug('process file: %s', filename)

            with DatasetReader(filename) as f:

                # Collect metadata per site, i.e. per job ID
                metadata_path = '/metadata'
                dataset_names = f.list_datasets(metadata_path)
                for name in dataset_names:
                    dataset_path = '{group}/{dataset}'.format(
                                        group=metadata_path,
                                        dataset=name)
                    data = f.read(dataset_path)
                    if len(data.shape) > 1:
                        raise DataError(
                                'Dataset must be one-dimensional: %s'
                                % dataset_path)
                    index = range(
                            job_index_count,
                            (1 + job_index_count)
                    )
                    out.write(dataset_path, data=data, index=index)
                job_index_count += 1

                # Collect features and segmentations per object
                for obj_name in object_names:
                    features_path = 'objects/%s/features' % obj_name
                    segmentation_path = 'objects/%s/segmentation' % obj_name

                    if f.exists(features_path):
                        dataset_names = f.list_datasets(features_path)
                        for name in dataset_names:
                            dataset_path = '{group}/{dataset}'.format(
                                            group=features_path,
                                            dataset=name)
                            data = f.read(dataset_path)
                            if len(data.shape) > 1:
                                raise DataError(
                                        'Dataset must be one-dimensional: %s'
                                        % dataset_path)
                            index = range(
                                    object_index_count[obj_name],
                                    (len(data) + object_index_count[obj_name])
                            )
                            out.write(dataset_path, data=data, index=index)

                    if f.exists(segmentation_path):
                        dataset_names = f.list_datasets(segmentation_path)
                        for name in dataset_names:
                            dataset_path = '{group}/{dataset}'.format(
                                            group=segmentation_path,
                                            dataset=name)
                            data = f.read(dataset_path)
                            if len(data.shape) > 1:
                                raise DataError(
                                        'Dataset must be one-dimensional: %s'
                                        % dataset_path)
                            index = range(
                                    object_index_count[obj_name],
                                    (len(data) + object_index_count[obj_name])
                            )
                            out.write(dataset_path, data=data, index=index)

                        group_names = f.list_groups(segmentation_path)
                        for g_name in group_names:
                            group_path = '{group}/{subgroup}'.format(
                                            group=segmentation_path,
                                            subgroup=g_name)
                            dataset_names = f.list_datasets(group_path)
                            for name in dataset_names:
                                dataset_path = '{group}/{dataset}'.format(
                                                group=group_path, dataset=name)
                                data = f.read(dataset_path)
                                if len(data.shape) > 1:
                                    raise DataError(
                                            'Dataset must be one-dimensional: %s'
                                            % dataset_path)
                                index = range(
                                        object_index_count[obj_name],
                                        (len(data) +
                                         object_index_count[obj_name])
                                )
                                out.write(dataset_path, data=data, index=index)

                    object_index_count[obj_name] += len(data)

            if delete_input_files:
                logger.debug('remove input file: %s', f)
                os.remove(filename)

def update_datasets(old_filename, new_filename):
    '''
    Recursively copy all datasets from one HDF5 file to a new HDF5 file without
    overwriting existing ones.

    Parameters
    ----------
    old_filename: str
        absolute path to the file whose content should be copied
    new_filename: str
        absolute path to the file, which should be updated
    '''
    with DatasetReader(old_filename) as old_file:
        with DatasetWriter(new_filename) as new_file:
            def copy_recursively(p):
                groups = old_file.list_groups(p)
                for g in groups:
                    group_path = '{group}/{subgroup}'.format(
                                    group=p, subgroup=g)
                    if g == 'coordinates':
                        # The coordinates for the visualization have to be
                        # recalculated in case the segmentation has changed.
                        continue
                    for d in old_file.list_datasets(group_path):
                        dataset_path = '{group}/{dataset}'.format(
                                            group=group_path, dataset=d)
                        if not new_file.exists(dataset_path):
                            # Keep the more recent dataset.
                            new_file.write(
                                    dataset_path,
                                    data=old_file.read(dataset_path))
                    copy_recursively(group_path)
            copy_recursively('/')
<|endoftext|>


<commit_before>import praw, time
import sqlite3
import re
import admin,records
url = 'http://www.google.com/?#q='
username = 'TheHelpfulBot'
depression_words = [
                    'I want to die',
                    'I want to kill myself',
                    'I hate life',
                    'I\'m having suicidal thoughts'
                    'I don\'t have a reason to live'
                    'I hate myself'
                    'I am a failure'
                    'I don\'t deserve to live'
                    'I can\'t do this anymore'

]
depression_responses = [
                      'I\'m so sorry to hear that you\'re in pain. If you are in serious pain and need help' + ', ' + '[please visit this site](https://afsp.org/)',
                      'I understand your pain. [This site might be able to help](https://afsp.org/)'
]
curious_words = [
                'I wonder why'
                'How does',
                'What if',
                'When did'
]

curious_responses = [
                    '[Here, let me help you with that](' + url + ')'
]

relationship_words= [
                    'How do I get a *friend*'
]

relationship_responses = [
                      'The most common way is to ask the person out'
                      'Sometimes the most important thing is simply being there for someone'

]

all_comment_types = [
                    depression_words,
					depression_responses,
                    curious_words,
					curious_responses,
                    relationship_words,
					relationship_responses
]

###########################################################################################
#Still working in things, but I'm gonna try to test this thing out tonight, if possible    #
###########################################################################################

#r = praw.Reddit("A helpful friend with useful advice")
#r.set_oauth_app_info(admin.app_id, admin.app_secret, admin.redirecturl)
#r.get_authorize_url('...', oauth.app_scopes, True)

def login():
	r = praw.Reddit("A friend providing useful information and helpful advice")
	r.set_oauth_app_info(admin.app_id, admin.app_secret, admin.redirecturl)
	r.refresh_access_token(admin.refresh_token)
	return r

sub = 'test'
maxposts = 100
url = 'http://www.google.com/?#q='
print('Logging in to Reddit...')

class CommentReply:

	def __init__(self, comment_type, response_type):
		self.comment_type = comment_type
		self.response_type = response_type

	def reply_to_comment(comment_type, reponse_type):
		comments = r.get_subreddit(sub).get_comments(limit=maxposts)
		for comment in comments:
			if comment.id not in answered_comments:
				try:
					author = comment.author.name
					if author.lower() != username.lower():
						comment_text = comment.body.lower()
						match = any(string.lower() in comment_text for word in comment_type)
						if match:
							print("Replying to " + author)
							comment.reply(response_type)
						else:
							pass
				except AttributeError:
					pass
				x.execute('INSERT INTO answered VALUES(?),'[comment.id])
				found.commit()

class SubmissionReply:

		def __init__(self, submission_type, submission_reply):
			self.submission_type = submission_type
			self.submission_reply = submission_reply

		def reply_to_submission(submission_type, _response_type):
			submissions = r.get_subreddit(sub).get_new(limit=maxposts)
			for submission in submissions:
				x.execute('SELECT * FROM answered WHERE SUBMISSION TEXT=?', [submission.id])
				if not x.fetchone:
					try:
						author = submission.author.name
						if author.lower() != username.lower():
							submission_text = submission.text.lower()
							match = any(string in submission_text for word in submission_type)
							if match:
								print('Replying to ' + author)
								submission.reply(response_type)
					except AtrributeError:
						pass
					x.execute('INSERT INTO answered VALUES(?)', [submission.id])
					found.commit()

while True:
	for i in range(len(all_comment_types)-1):
        CommentReply.reply_to_comment(all_comment_types[i], all_coment_types[i+1])
        time.sleep(5)
<commit_msg>This might be the beta version<commit_after>import praw, time
import re, random
import admin,records
url = 'http://www.google.com/?#q='
username = 'TheHelpfulBot'
depression_words = [
                    'I want to die',
                    'I want to kill myself',
                    'I hate life',
                    'I\'m having suicidal thoughts'
                    'I don\'t have a reason to live'
                    'I hate myself'
                    'I am a failure'
                    'I don\'t deserve to live'
                    'I can\'t do this anymore'

]
depression_responses = [
                      'I\'m so sorry to hear that you\'re in pain. If you are in serious pain and need help' + ', ' + '[please visit this site](https://afsp.org/)',
                      'I understand your pain. [This site might be able to help](https://afsp.org/)'
]
curious_words = [
                'I wonder why'
                'How does',
                'What if',
                'When did'
]

curious_responses = [
                    '[Here, let me help you with that](' + url + ')'
]

relationship_words= [
                    'How do I get a *friend*'
]

relationship_responses = [
                      'The most common way is to ask the person out'
                      'Sometimes the most important thing is simply being there for someone'

]

all_comment_types = [
                    depression_words,
					depression_responses,
                    curious_words,
					curious_responses,
                    relationship_words,
					relationship_responses
]

###########################################################################################
#Still working in things, but I'm gonna try to test this thing out tonight, if possible    #
###########################################################################################

#r = praw.Reddit("A helpful friend with useful advice")
#r.set_oauth_app_info(admin.app_id, admin.app_secret, admin.redirecturl)
#r.get_authorize_url('...', oauth.app_scopes, True)

def login():
	r = praw.Reddit("A friend providing useful information and helpful advice")
	r.set_oauth_app_info(admin.app_id, admin.app_secret, admin.redirecturl)
	r.refresh_access_token(admin.refresh_token)
	return r

sub = 'test'
maxposts = 100
url = 'http://www.google.com/?#q='
print('Logging in to Reddit...')

class CommentReply:

	def __init__(self, comment_type, response_type):
		self.comment_type = comment_type
		self.response_type = response_type

	def reply_to_comment(comment_type, reponse_type):
		comments = r.get_subreddit(sub).get_comments(limit=maxposts)
		for comment in comments:
			if comment.id not in answered_comments:
				try:
					author = comment.author.name
					if author.lower() != username.lower():
						comment_text = comment.body.lower()
						match = any(string.lower() in comment_text for word in comment_type)
						if match:
							print("Replying to " + author)
							comment.reply(random.choice(response_type))
                            with open('records.py', 'a') as rec:
                                answered_comments.append(comment.id)
                                rec.close()
				except AttributeError:
					pass

class SubmissionReply:

		def __init__(self, submission_type, submission_reply):
			self.submission_type = submission_type
			self.submission_reply = submission_reply

		def reply_to_submission(submission_type, _response_type):
			submissions = r.get_subreddit(sub).get_new(limit=maxposts)
			for submission in submissions:
				if submission.id not in answered_submissions:
					try:
						author = submission.author.name
						if author.lower() != username.lower():
							submission_text = submission.text.lower()
							match = any(string in submission_text for word in submission_type)
                            with open('records.py', 'a') as rec:
                                answered_submissions.append(submission.id)
                                rec.close()
							if match:
								print('Replying to ' + author)
								submission.reply(random.choice(response_type))
					except AtrributeError:
						pass

while True:
	for i in range(len(all_comment_types)-1):
        CommentReply.reply_to_comment(all_comment_types[i], all_coment_types[i+1])
        time.sleep(5)
<|endoftext|>


<commit_before>import os.path as p
import json
import datetime
import importlib
import logging
import re

from flask import request
from flask.ext.jwt import jwt_required
from werkzeug import secure_filename
from sqlalchemy.orm.exc import MultipleResultsFound

import tmlib.models as tm
from tmlib.models.status import FileUploadStatus
from tmlib.workflow.metaconfig import get_microscope_type_regex

from tmserver.extensions import redis_store
from tmserver.api import api
from tmserver.util import decode_query_ids, decode_form_ids
from tmserver.util import assert_query_params, assert_form_params
from tmserver.error import *

logger = logging.getLogger(__name__)

@api.route(
    '/experiments/<experiment_id>/acquisitions/<acquisition_id>/upload/register',
    methods=['POST']
)
@jwt_required()
@assert_form_params('files')
@jwt_required()
@decode_query_ids()
def register_upload(experiment_id, acquisition_id):
    """
    Tell the server that an upload for this acquisition is imminent.
    The client should wait for this response before uploading files.

    Request
    -------

    {
        files: Array<string>
    }

    Response
    --------

    Response 200 or 500

    """
    data = request.get_json()

    if len(data.get('files', [])) == 0:
        raise MalformedRequestError(
            'No files supplied. Cannot register upload.'
        )

    with tm.utils.ExperimentSession(experiment_id) as session:
        experiment = session.query(tm.Experiment).one()
        microscope_type = experiment.microscope_type
        img_regex, metadata_regex = get_microscope_type_regex(microscope_type)
        acquisition = session.query(tm.Acquisition).get(acquisition_id)
        img_filenames = [f.name for f in acquisition.microscope_image_files]
        img_files = [
            tm.MicroscopeImageFile(
                name=secure_filename(f), acquisition_id=acquisition.id
            )
            for f in data['files']
            if img_regex.search(f) and
            secure_filename(f) not in img_filenames
        ]
        meta_filenames = [f.name for f in acquisition.microscope_metadata_files]
        meta_files = [
            tm.MicroscopeMetadataFile(
                name=secure_filename(f), acquisition_id=acquisition.id
            )
            for f in data['files']
            if metadata_regex.search(f) and
            secure_filename(f) not in meta_filenames
        ]

        session.bulk_save_objects(img_files + meta_files)

        # Trigger creation of directories
        acquisition.location
        acquisition.microscope_images_location
        acquisition.microscope_metadata_location

    with tm.utils.ExperimentSession(experiment_id) as session:
        image_file_names = session.query(tm.MicroscopeImageFile.name).\
            filter(tm.MicroscopeImageFile.status != FileUploadStatus.COMPLETE).\
            all()
        metadata_file_names = session.query(tm.MicroscopeMetadataFile.name).\
            filter(tm.MicroscopeMetadataFile.status != FileUploadStatus.COMPLETE).\
            all()
        return jsonify({
            'data': [f.name for f in image_file_names + metadata_file_names]
        })

@api.route(
    '/experiments/<experiment_id>/acquisitions/<acquisition_id>/upload/validity-check',
    methods=['POST']
)
@jwt_required()
@assert_form_params('files')
@decode_query_ids()
def file_validity_check(experiment_id, acquisition_id):
    data = json.loads(request.data)
    if not 'files' in data:
        raise MalformedRequestError()
    if not type(data['files']) is list:
        raise MalformedRequestError('No image files provided.')

    def check_file(fname):
        is_imgfile = imgfile_regex.search(fname) is not None
        is_metadata_file = metadata_regex.search(fname) is not None
        return is_metadata_file or is_imgfile

    with tm.utils.ExperimentSession(experiment_id) as session:
        experiment = session.query(tm.Experiment).one()
        microscope_type = experiment.microscope_type
    imgfile_regex, metadata_regex = get_microscope_type_regex(microscope_type)

    # TODO: check if metadata files are missing
    is_valid = [check_file(f['name']) for f in data['files']]

    return jsonify({
        'is_valid': is_valid
    })

@api.route(
    '/experiments/<experiment_id>/acquisitions/<acquisition_id>/upload/upload-file',
    methods=['POST']
)
@jwt_required()
@decode_query_ids()
def upload_file(experiment_id, acquisition_id):
    # TODO: shouldn't this be a PUT request?
    f = request.files.get('file')

    # Get the file form the form
    if not f:
        raise MalformedRequestError('Missing file entry in the upload request.')

    with tm.utils.ExperimentSession(experiment_id) as session:
        acquisition = session.query(tm.Acquisition).get(acquisition_id)
        if acquisition.status == FileUploadStatus.COMPLETE:
            logger.info('acquisition already complete')
            return jsonify(message='Acquisition complete')

        filename = secure_filename(f.filename)
        imgfile = session.query(tm.MicroscopeImageFile).\
            filter_by(name=filename, acquisition_id=acquisition_id).\
            one_or_none()
        metafile = session.query(tm.MicroscopeMetadataFile).\
            filter_by(name=filename, acquisition_id=acquisition_id).\
            one_or_none()

        is_imgfile = imgfile is not None
        is_metafile = metafile is not None
        if not is_metafile and not is_imgfile:
            raise MalformedRequestError(
                'File was not registered: "%s"' % filename
            )
        elif is_imgfile:
            file_obj = imgfile
        elif is_metafile:
            file_obj = metafile
        else:
            raise MalformedRequestError(
                'File was registered as both image and metadata file: "%s"'
                % filename
            )

        if file_obj.status == FileUploadStatus.COMPLETE:
            logger.info('file "%s" already uploaded')
            return jsonify(message='File already uploaded')
        elif file_obj.status == FileUploadStatus.UPLOADING:
            logger.info('file "%s" already uploading')
            return jsonify(message='File upload already in progress')

        logger.info('upload file "%s"', filename)
        file_obj.status = FileUploadStatus.UPLOADING
        session.add(file_obj)
        session.commit()

        try:
            f.save(file_obj.location)
            file_obj.status = FileUploadStatus.COMPLETE
        except Exception as error:
            file_obj.status = FileUploadStatus.FAILED
            raise InternalServerError(
                'Upload of file failed: %s' % str(error)
            )

    return jsonify(message='ok')
<commit_msg>Add view function to get uploaded file count<commit_after>import os.path as p
import json
import datetime
import importlib
import logging
import re

from flask import request
from flask.ext.jwt import jwt_required
from werkzeug import secure_filename
from sqlalchemy.orm.exc import MultipleResultsFound

import tmlib.models as tm
from tmlib.models.status import FileUploadStatus
from tmlib.workflow.metaconfig import get_microscope_type_regex

from tmserver.extensions import redis_store
from tmserver.api import api
from tmserver.util import decode_query_ids, decode_form_ids
from tmserver.util import assert_query_params, assert_form_params
from tmserver.error import *

logger = logging.getLogger(__name__)

@api.route(
    '/experiments/<experiment_id>/acquisitions/<acquisition_id>/upload/register',
    methods=['POST']
)
@jwt_required()
@assert_form_params('files')
@jwt_required()
@decode_query_ids()
def register_upload(experiment_id, acquisition_id):
    """
    Tell the server that an upload for this acquisition is imminent.
    The client should wait for this response before uploading files.

    Request
    -------

    {
        files: Array<string>
    }

    Response
    --------

    Response 200 or 500

    """
    data = request.get_json()
    files = data['files']

    if len(files) == 0:
        raise MalformedRequestError(
            'No files supplied. Cannot register upload.'
        )

    with tm.utils.ExperimentSession(experiment_id) as session:
        experiment = session.query(tm.Experiment).one()
        microscope_type = experiment.microscope_type
        img_regex, metadata_regex = get_microscope_type_regex(microscope_type)
        acquisition = session.query(tm.Acquisition).get(acquisition_id)
        img_filenames = [f.name for f in acquisition.microscope_image_files]
        img_files = [
            tm.MicroscopeImageFile(
                name=secure_filename(f), acquisition_id=acquisition.id
            )
            for f in files
            if img_regex.search(f) and
            secure_filename(f) not in img_filenames
        ]
        meta_filenames = [f.name for f in acquisition.microscope_metadata_files]
        meta_files = [
            tm.MicroscopeMetadataFile(
                name=secure_filename(f), acquisition_id=acquisition.id
            )
            for f in files
            if metadata_regex.search(f) and
            secure_filename(f) not in meta_filenames
        ]

        session.bulk_save_objects(img_files + meta_files)

        # Trigger creation of directories
        acquisition.location
        acquisition.microscope_images_location
        acquisition.microscope_metadata_location

    with tm.utils.ExperimentSession(experiment_id) as session:
        image_file_names = session.query(tm.MicroscopeImageFile.name).\
            filter(tm.MicroscopeImageFile.status != FileUploadStatus.COMPLETE).\
            all()
        metadata_file_names = session.query(tm.MicroscopeMetadataFile.name).\
            filter(tm.MicroscopeMetadataFile.status != FileUploadStatus.COMPLETE).\
            all()
        return jsonify({
            'data': [f.name for f in image_file_names + metadata_file_names]
        })

@api.route(
    '/experiments/<experiment_id>/acquisitions/<acquisition_id>/upload/validity-check',
    methods=['POST']
)
@jwt_required()
@assert_form_params('files')
@decode_query_ids()
def file_validity_check(experiment_id, acquisition_id):
    data = json.loads(request.data)
    if not 'files' in data:
        raise MalformedRequestError()
    if not type(data['files']) is list:
        raise MalformedRequestError('No image files provided.')

    def check_file(fname):
        is_imgfile = imgfile_regex.search(fname) is not None
        is_metadata_file = metadata_regex.search(fname) is not None
        return is_metadata_file or is_imgfile

    with tm.utils.ExperimentSession(experiment_id) as session:
        experiment = session.query(tm.Experiment).one()
        microscope_type = experiment.microscope_type
    imgfile_regex, metadata_regex = get_microscope_type_regex(microscope_type)

    # TODO: check if metadata files are missing
    is_valid = [check_file(f['name']) for f in data['files']]

    return jsonify({
        'is_valid': is_valid
    })

@api.route(
    '/experiments/<experiment_id>/acquisitions/<acquisition_id>/upload/upload-file',
    methods=['POST']
)
@jwt_required()
@decode_query_ids()
def upload_file(experiment_id, acquisition_id):
    # TODO: shouldn't this be a PUT request?
    f = request.files.get('file')

    # Get the file form the form
    if not f:
        raise MalformedRequestError('Missing file entry in the upload request.')

    with tm.utils.ExperimentSession(experiment_id) as session:
        acquisition = session.query(tm.Acquisition).get(acquisition_id)
        if acquisition.status == FileUploadStatus.COMPLETE:
            logger.info('acquisition already complete')
            return jsonify(message='Acquisition complete')

        filename = secure_filename(f.filename)
        imgfile = session.query(tm.MicroscopeImageFile).\
            filter_by(name=filename, acquisition_id=acquisition_id).\
            one_or_none()
        metafile = session.query(tm.MicroscopeMetadataFile).\
            filter_by(name=filename, acquisition_id=acquisition_id).\
            one_or_none()

        is_imgfile = imgfile is not None
        is_metafile = metafile is not None
        if not is_metafile and not is_imgfile:
            raise MalformedRequestError(
                'File was not registered: "%s"' % filename
            )
        elif is_imgfile:
            file_obj = imgfile
        elif is_metafile:
            file_obj = metafile
        else:
            raise MalformedRequestError(
                'File was registered as both image and metadata file: "%s"'
                % filename
            )

        if file_obj.status == FileUploadStatus.COMPLETE:
            logger.info('file "%s" already uploaded')
            return jsonify(message='File already uploaded')
        elif file_obj.status == FileUploadStatus.UPLOADING:
            logger.info('file "%s" already uploading')
            return jsonify(message='File upload already in progress')

        logger.info('upload file "%s"', filename)
        file_obj.status = FileUploadStatus.UPLOADING
        session.add(file_obj)
        session.commit()

        try:
            f.save(file_obj.location)
            file_obj.status = FileUploadStatus.COMPLETE
        except Exception as error:
            file_obj.status = FileUploadStatus.FAILED
            raise InternalServerError(
                'Upload of file failed: %s' % str(error)
            )

    return jsonify(message='ok')

@api.route(
    '/experiments/<experiment_id>/acquisitions/<acquisition_id>/upload/count',
    methods=['GET']
)
@jwt_required()
@decode_query_ids()
def get_uploaded_file_count(experiment_id, acquisition_id):
    with tm.utils.ExperimentSession(experiment_id) as session:
        acquisition = session.query(tm.Acquisition).get(acquisition_id)
        n_imgfiles = session.query(tm.MicroscopeImageFile).\
            filter_by(
                status=FileUploadStatus.COMPLETE, acquisition_id=acquisition_id
            ).\
            count()
        n_metafiles = session.query(tm.MicroscopeMetadataFile).\
            filter_by(
                status=FileUploadStatus.COMPLETE, acquisition_id=acquisition_id
            ).\
            count()
    return jsonify({
        'data': n_imgfiles + n_metafiles
    })

<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import sys

import logging
import logging.config
import time
import threading

from github import GithubAPI, webhook_server, find_mentions
from slack import SlackApi
from user_mapping import UserMapping, UserAccount
import env

reload(sys)
sys.setdefaultencoding('utf-8')

class WebhookEvents(object):
    '''
    https://developer.github.com/webhooks/
    '''

    def __init__(self, slack, mapping, logger):
        self.slack = slack
        self.mapping = mapping
        self.logger = logger

    def on_mentions(self, slack_data):
        # Find any mentions
        mentions = find_mentions(slack_data.get("message"))
        for mention in mentions:
            # See if the user is listed
            user = self.mapping.get_user(github=mention)
            if user is None:
                self.logger.error("Unmapped user found: {user}".format(user=mention))

                # Not found, see if its a valid slack user
                if self.slack.find_user(mention) is None:
                    break

                # If it worked create a temporary mapping
                user = UserAccount(
                    name=mention,
                    github=mention,
                    slack=mention,
                )

            # Send individual mentions
            self.on_mention(slack_data, user)

    def on_mention(self, slack_data, mention):
        slack_data = slack_data.copy()
        slack_data["user"] = mention

        branch = slack_data.get("branch", False)
        if branch is False:
            slack_data["branch"] = ""

        #####################################
        # Formats to slack style
        attachment = {
            "fallback": "You've been Mentioned: {link}\nSender: {assigner}\nMentioned User: {user}\nRepo: {repo_name} {branch}\nSource: {source}".format(**slack_data),
            "color": "#36a64f",
            "title": "You've been mentioned in a {source}".format(**slack_data),
            "title_link": "{link}".format(**slack_data),
            "fields": [
                {
                    "title": "Repo",
                    "value": slack_data["repo_name"],
                    "short": True,
                }
            ],
            "footer": "Github Mention",

            # TODO: Hardcoded slack icon
            "footer_icon": "https://avatars.slack-edge.com/2016-09-30/86125165617_c717ddd0e0e41b6b2597_48.jpg",
        }

        # Not all things have a branch
        if branch is not False:
            attachment["fields"].append({
                "title": "Branch",
                "value": slack_data["branch"],
                "short": True,
            })

        #################################
        # Send a slack message
        self.slack.send_message(
            user=slack_data["assigner"],
            target=mention,
            text=slack_data["message"],
            attachment=attachment,
        )

    ####################################################################
    # Github Events

    def on_commit_comment_created(self, data):
        ###############################
        # Pulls our github info
        assigner = self.mapping.get_user(
            github=data.get("sender").get("login")
        )

        avatar_url = data.get("sender").get("avatar_url")

        comment = data.get("comment")
        comment_url = comment.get("html_url")
        message = comment.get("body")

        repo = data.get("repository")
        repo_name = repo.get("full_name")

        slack_data = {
            "message": message,
            "link": comment_url,
            "assigner": assigner,
            "avatar_url": avatar_url,
            "repo_name": repo_name,
            "source": "Commit",
        }

        # See if someone was mentioned
        self.on_mentions(slack_data)

    def on_issue_comment_created(self, data):
        return self.on_issue_comment(data)

    def on_issue_comment_edited(self, data):
        return self.on_issue_comment(data)

    def on_issue_comment(self, data):
        ###############################
        # Pulls our github info
        assigner = self.mapping.get_user(
            github=data.get("sender").get("login")
        )
        avatar_url = data.get("sender").get("avatar_url")

        # Some issues are also a PR
        pr = data.get("pull_request", False)
        if pr:
            branch = pr.get("head").get("ref")
        else:
            branch = False

        comment = data.get("comment")
        comment_url = comment.get("html_url")
        message = comment.get("body")

        repo = data.get("repository")
        repo_name = repo.get("full_name")

        slack_data = {
            "message": message,
            "link": comment_url,
            "assigner": assigner,
            "avatar_url": avatar_url,
            "repo_name": repo_name,
            "source": "PR Comment",
        }

        # See if someone was mentioned
        self.on_mentions(slack_data)

    def on_pull_request_review_comment_edited(self, data):
        return self.on_pull_request_review_comment(data)

    def on_pull_request_review_comment_created(self, data):
        return self.on_pull_request_review_comment(data)

    def on_pull_request_review_comment(self, data):
        ###############################
        # Pulls our github info
        assigner = self.mapping.get_user(
            github=data.get("sender").get("login")
        )

        pr = data.get("pull_request")
        pr_title = pr.get("title")
        pr_branch = pr.get("head").get("ref")

        comment = data.get("comment")
        comment_url = comment.get("html_url")
        message = comment.get("body")

        repo = data.get("repository")
        repo_name = repo.get("full_name")

        slack_data = {
            "message": message,
            "link": comment_url,
            "branch": pr_branch,
            "assigner": assigner,
            "repo_name": repo_name,
            "source": "PR Review",
        }

        # See if someone was mentioned
        self.on_mentions(slack_data)

    def on_pull_request_opened(self, data):
        ###############################
        # Pulls our github info
        assigner = self.mapping.get_user(
            github=data.get("sender").get("login")
        )
        avatar_url = data.get("sender").get("avatar_url")

        pr = data.get("pull_request")
        pr_message = pr.get("body")
        pr_branch = pr.get("head").get("ref")
        pr_url = pr.get("html_url")

        repo = data.get("repository")
        repo_name = repo.get("full_name")

        slack_data = {
            "message": pr_message,
            "link": pr_url,
            "assigner": assigner,
            "avatar_url": avatar_url,
            "repo_name": repo_name,
            "source": "Opened PR Description",
        }

        # See if someone was mentioned
        self.on_mentions(slack_data)

    def on_pull_request_assigned(self, data):
        ###############################
        # Pulls our github info
        user = self.mapping.get_user(
            github=data.get("assignee").get("login")
        )
        assigner = self.mapping.get_user(
            github=data.get("sender").get("login")
        )
        avatar_url = data.get("sender").get("avatar_url")

        pr = data.get("pull_request")
        pr_message = pr.get("body")
        pr_branch = pr.get("head").get("ref")
        pr_url = pr.get("html_url")
        pr_title = pr.get("title")
        pr_number = pr.get("number")

        repo = data.get("repository")
        repo_name = repo.get("full_name")

        #####################################
        # Formats to slack style
        attachment = {
            "fallback": "PR Assigned: {link}\n{title} #{id}: {message}\nAssigned By: {assigner}\nAssigned To: {user}\nRepo: {repo_name} {branch}".format(
                link=pr_url,
                title=pr_title,
                id=pr_number,
                message=pr_message,
                assigner=assigner,
                user=user,
                repo_name=repo_name,
                branch=pr_branch,
            ),
            "color": "#36a64f",
            "title": "{title} #{id} has been assigned to you".format(id=pr_number, title=pr_title),
            "title_link": "{link}".format(link=pr_url),
            "text": pr_message,
            "fields": [
                {
                    "title": "Repo",
                    "value": "{repo_name}@{branch}".format(repo_name=repo_name, branch=pr_branch),
                    "short": True,
                },
                {
                    "title": "Assigned By",
                    "value": assigner.name,
                    "short": True,
                },
            ],
            "footer": "Github PR",
        }

        #################################
        # Send a slack message
        self.slack.send_message(
            user=assigner,
            target=user,
            text="",
            attachment=attachment,
        )

def heartbeat(logger, seconds):
    while True:
        logger.info("Hearbeat")
        time.sleep(seconds)

def setup():
    logging.config.dictConfig(env.LOGGING)
    main_logger = logging.getLogger('')

    # Enable the heartbeat
    if env.HEARTBEAT_DURATION >= 1:
        heartbeat_logger = logging.getLogger('heartbeat')
        heartbeat_thread = threading.Thread(target=heartbeat, kwargs={
            "logger": heartbeat_logger,
            "seconds": env.HEARTBEAT_DURATION,
        })
        heartbeat_thread.daemon = True
        heartbeat_thread.start()

    # Start the server
    slack_logger = logging.getLogger('messenger')
    mapping = UserMapping(env.USER_MAPPING)
    slack_client = SlackApi(env.SLACK["TOKEN"], slack_logger)
    events = WebhookEvents(slack_client, mapping, slack_logger)

    github_logger = logging.getLogger('listener')
    application = webhook_server(events, github_logger)

    # Log Status
    main_logger.info('Started')

    return application

if __name__ == "__main__":
    app = setup()
    app.run(port=8080, host="0.0.0.0")
<commit_msg>Adds Slack Icon<commit_after>#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import sys

import logging
import logging.config
import time
import threading

from github import GithubAPI, webhook_server, find_mentions
from slack import SlackApi
from user_mapping import UserMapping, UserAccount
import env

reload(sys)
sys.setdefaultencoding('utf-8')

class WebhookEvents(object):
    '''
    https://developer.github.com/webhooks/
    '''

    def __init__(self, slack, mapping, logger):
        self.slack = slack
        self.mapping = mapping
        self.logger = logger

    def on_mentions(self, slack_data):
        # Find any mentions
        mentions = find_mentions(slack_data.get("message"))
        for mention in mentions:
            # See if the user is listed
            user = self.mapping.get_user(github=mention)
            if user is None:
                self.logger.error("Unmapped user found: {user}".format(user=mention))

                # Not found, see if its a valid slack user
                if self.slack.find_user(mention) is None:
                    break

                # If it worked create a temporary mapping
                user = UserAccount(
                    name=mention,
                    github=mention,
                    slack=mention,
                )

            # Send individual mentions
            self.on_mention(slack_data, user)

    def on_mention(self, slack_data, mention):
        slack_data = slack_data.copy()
        slack_data["user"] = mention

        branch = slack_data.get("branch", False)
        if branch is False:
            slack_data["branch"] = ""

        #####################################
        # Formats to slack style
        attachment = {
            "fallback": "You've been Mentioned: {link}\nSender: {assigner}\nMentioned User: {user}\nRepo: {repo_name} {branch}\nSource: {source}".format(**slack_data),
            "color": "#36a64f",
            "title": "You've been mentioned in a {source}".format(**slack_data),
            "title_link": "{link}".format(**slack_data),
            "fields": [
                {
                    "title": "Repo",
                    "value": slack_data["repo_name"],
                    "short": True,
                }
            ],
            "footer": "Github Mention",

            # TODO: Hardcoded slack icon
            "footer_icon": "https://avatars.slack-edge.com/2016-09-30/86125165617_c717ddd0e0e41b6b2597_48.jpg",
        }

        # Not all things have a branch
        if branch is not False:
            attachment["fields"].append({
                "title": "Branch",
                "value": slack_data["branch"],
                "short": True,
            })

        #################################
        # Send a slack message
        self.slack.send_message(
            user=slack_data["assigner"],
            target=mention,
            text=slack_data["message"],
            attachment=attachment,
        )

    ####################################################################
    # Github Events

    def on_commit_comment_created(self, data):
        ###############################
        # Pulls our github info
        assigner = self.mapping.get_user(
            github=data.get("sender").get("login")
        )

        avatar_url = data.get("sender").get("avatar_url")

        comment = data.get("comment")
        comment_url = comment.get("html_url")
        message = comment.get("body")

        repo = data.get("repository")
        repo_name = repo.get("full_name")

        slack_data = {
            "message": message,
            "link": comment_url,
            "assigner": assigner,
            "avatar_url": avatar_url,
            "repo_name": repo_name,
            "source": "Commit",
        }

        # See if someone was mentioned
        self.on_mentions(slack_data)

    def on_issue_comment_created(self, data):
        return self.on_issue_comment(data)

    def on_issue_comment_edited(self, data):
        return self.on_issue_comment(data)

    def on_issue_comment(self, data):
        ###############################
        # Pulls our github info
        assigner = self.mapping.get_user(
            github=data.get("sender").get("login")
        )
        avatar_url = data.get("sender").get("avatar_url")

        # Some issues are also a PR
        pr = data.get("pull_request", False)
        if pr:
            branch = pr.get("head").get("ref")
        else:
            branch = False

        comment = data.get("comment")
        comment_url = comment.get("html_url")
        message = comment.get("body")

        repo = data.get("repository")
        repo_name = repo.get("full_name")

        slack_data = {
            "message": message,
            "link": comment_url,
            "assigner": assigner,
            "avatar_url": avatar_url,
            "repo_name": repo_name,
            "source": "PR Comment",
        }

        # See if someone was mentioned
        self.on_mentions(slack_data)

    def on_pull_request_review_comment_edited(self, data):
        return self.on_pull_request_review_comment(data)

    def on_pull_request_review_comment_created(self, data):
        return self.on_pull_request_review_comment(data)

    def on_pull_request_review_comment(self, data):
        ###############################
        # Pulls our github info
        assigner = self.mapping.get_user(
            github=data.get("sender").get("login")
        )

        pr = data.get("pull_request")
        pr_title = pr.get("title")
        pr_branch = pr.get("head").get("ref")

        comment = data.get("comment")
        comment_url = comment.get("html_url")
        message = comment.get("body")

        repo = data.get("repository")
        repo_name = repo.get("full_name")

        slack_data = {
            "message": message,
            "link": comment_url,
            "branch": pr_branch,
            "assigner": assigner,
            "repo_name": repo_name,
            "source": "PR Review",
        }

        # See if someone was mentioned
        self.on_mentions(slack_data)

    def on_pull_request_opened(self, data):
        ###############################
        # Pulls our github info
        assigner = self.mapping.get_user(
            github=data.get("sender").get("login")
        )
        avatar_url = data.get("sender").get("avatar_url")

        pr = data.get("pull_request")
        pr_message = pr.get("body")
        pr_branch = pr.get("head").get("ref")
        pr_url = pr.get("html_url")

        repo = data.get("repository")
        repo_name = repo.get("full_name")

        slack_data = {
            "message": pr_message,
            "link": pr_url,
            "assigner": assigner,
            "avatar_url": avatar_url,
            "repo_name": repo_name,
            "source": "Opened PR Description",
        }

        # See if someone was mentioned
        self.on_mentions(slack_data)

    def on_pull_request_assigned(self, data):
        ###############################
        # Pulls our github info
        user = self.mapping.get_user(
            github=data.get("assignee").get("login")
        )
        assigner = self.mapping.get_user(
            github=data.get("sender").get("login")
        )
        avatar_url = data.get("sender").get("avatar_url")

        pr = data.get("pull_request")
        pr_message = pr.get("body")
        pr_branch = pr.get("head").get("ref")
        pr_url = pr.get("html_url")
        pr_title = pr.get("title")
        pr_number = pr.get("number")

        repo = data.get("repository")
        repo_name = repo.get("full_name")

        #####################################
        # Formats to slack style
        attachment = {
            "fallback": "PR Assigned: {link}\n{title} #{id}: {message}\nAssigned By: {assigner}\nAssigned To: {user}\nRepo: {repo_name} {branch}".format(
                link=pr_url,
                title=pr_title,
                id=pr_number,
                message=pr_message,
                assigner=assigner,
                user=user,
                repo_name=repo_name,
                branch=pr_branch,
            ),
            "color": "#36a64f",
            "title": "{title} #{id} has been assigned to you".format(id=pr_number, title=pr_title),
            "title_link": "{link}".format(link=pr_url),
            "text": pr_message,
            "fields": [
                {
                    "title": "Repo",
                    "value": "{repo_name}@{branch}".format(repo_name=repo_name, branch=pr_branch),
                    "short": True,
                },
                {
                    "title": "Assigned By",
                    "value": assigner.name,
                    "short": True,
                },
            ],
            "footer": "Github PR",

            # TODO: Hardcoded slack icon
            "footer_icon": "https://avatars.slack-edge.com/2016-09-30/86125165617_c717ddd0e0e41b6b2597_48.jpg",
        }

        #################################
        # Send a slack message
        self.slack.send_message(
            user=assigner,
            target=user,
            text="",
            attachment=attachment,
        )

def heartbeat(logger, seconds):
    while True:
        logger.info("Hearbeat")
        time.sleep(seconds)

def setup():
    logging.config.dictConfig(env.LOGGING)
    main_logger = logging.getLogger('')

    # Enable the heartbeat
    if env.HEARTBEAT_DURATION >= 1:
        heartbeat_logger = logging.getLogger('heartbeat')
        heartbeat_thread = threading.Thread(target=heartbeat, kwargs={
            "logger": heartbeat_logger,
            "seconds": env.HEARTBEAT_DURATION,
        })
        heartbeat_thread.daemon = True
        heartbeat_thread.start()

    # Start the server
    slack_logger = logging.getLogger('messenger')
    mapping = UserMapping(env.USER_MAPPING)
    slack_client = SlackApi(env.SLACK["TOKEN"], slack_logger)
    events = WebhookEvents(slack_client, mapping, slack_logger)

    github_logger = logging.getLogger('listener')
    application = webhook_server(events, github_logger)

    # Log Status
    main_logger.info('Started')

    return application

if __name__ == "__main__":
    app = setup()
    app.run(port=8080, host="0.0.0.0")
<|endoftext|>


<commit_before>__version_info__ = (1, 3, 5, None)

# Dot-connect all but the last. Last is dash-connected if not None.
__version__ = '.'.join([str(i) for i in __version_info__[:-1]])
if __version_info__[-1] is not None:
    __version__ += ('-%s' % (__version_info__[-1],))

# context processor to add version to the template environment
def context_extras(request):
    return {
        # software version
        'SW_VERSION': __version__,
        # Alternate names for social-auth backends,
        # to be used for display and font-awesome icon (lowercased)
        # If not entered here, backend name will be used as-is for
        # icon and title-cased for display (i.e., twitter / Twitter).
        'backend_names': {
            'github': 'GitHub',
            'google-oauth2': 'Google',
        },
    }

<commit_msg>Bump version to 1.3.6<commit_after>__version_info__ = (1, 3, 6, None)

# Dot-connect all but the last. Last is dash-connected if not None.
__version__ = '.'.join([str(i) for i in __version_info__[:-1]])
if __version_info__[-1] is not None:
    __version__ += ('-%s' % (__version_info__[-1],))

# context processor to add version to the template environment
def context_extras(request):
    return {
        # software version
        'SW_VERSION': __version__,
        # Alternate names for social-auth backends,
        # to be used for display and font-awesome icon (lowercased)
        # If not entered here, backend name will be used as-is for
        # icon and title-cased for display (i.e., twitter / Twitter).
        'backend_names': {
            'github': 'GitHub',
            'google-oauth2': 'Google',
        },
    }

<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding=utf-8 -*-

import sys
import os

TESTS_PATH = os.path.join(os.environ["SRC_DIR"], "bindings", "python", "tests")
sys.path.append(TESTS_PATH)

import read
import write
<commit_msg>Remove outdated tests<commit_after><|endoftext|>


<commit_before>import websocket
import json
import requests
import os
import ssl
from collections import namedtuple
import re
import urlparse

###VARIABLES THAT YOU NEED TO SET MANUALLY IF NOT ON HEROKU#####
try:
	MESSAGE = os.environ['WELCOME-MESSAGE']
	TOKEN = os.environ['SLACK-TOKEN']
except:
	MESSAGE = 'Manually set the Message if youre not running through heroku or have not set vars in ENV'
	TOKEN = 'Manually set the API Token if youre not running through heroku or have not set vars in ENV'
###############################################################

_self_uid = None

SlackURL = namedtuple('SlackURL', ['original', 'transformed'])

def normalize_url_human(url):
    """
    >>> normalize_url_human("http://www.google.com").geturl()
    '//google.com'
    >>> normalize_url_human("https://google.com").geturl()
    '//google.com'
    >>> normalize_url_human("https://google.com/").geturl()
    '//google.com'
    >>> normalize_url_human("https://google.com/derp").geturl()
    '//google.com/derp'
    """

    parsed_url = urlparse.urlparse(url)
    dict_ = parsed_url._asdict()
    dict_['scheme'] = ""
    dict_['netloc'] = dict_['netloc'][4:] if dict_['netloc'].startswith("www.") else dict_['netloc']
    dict_['path'] = "" if dict_['path'] == "/" else dict_['path']

    return urlparse.ParseResult(**dict_)

def is_human_equal(url1, url2):
    """
    >>> is_human_equal("http://google.com/", "http://google.com/")
    True
    >>> is_human_equal("http://google.com/", "https://google.com/")
    True
    >>> is_human_equal("http://google.com/", "http://bing.com/")
    False
    >>> is_human_equal("http://google.com/", "http://www.google.com/")
    True
    >>> is_human_equal("http://google.com", "http://google.com/")
    True
    """

    return normalize_url_human(url1) == normalize_url_human(url2)

def extract_slack_urls(message):
    """
    >>> extract_slack_urls("derp <http://google.com|google.com> herp")
    [SlackURL(original='google.com', transformed='http://google.com')]
    >>> extract_slack_urls("derp <http://google.com|google.com> <http://bing.com|bing.com> herp")
    [SlackURL(original='google.com', transformed='http://google.com'), SlackURL(original='bing.com', transformed='http://bing.com')]
    >>> extract_slack_urls("derp <http://bit.ly/installfreemyapps> herp")
    [SlackURL(original='http://bit.ly/installfreemyapps', transformed='http://bit.ly/installfreemyapps')]
    >>> extract_slack_urls("derp google.com herp")
    []
    """

    def slack_url(wrapped_url):
        if '|' in wrapped_url:
            transformed_url, original_url = wrapped_url.split('|', 1)
        else:
            transformed_url = original_url = wrapped_url

        return SlackURL(original_url, transformed_url)

    wrapped_urls = re.findall(r'<(http[^>]+)>', message)

    return [slack_url(wrapped_url) for wrapped_url in wrapped_urls]

def send_message(cid, text):
    return requests.post('https://slack.com/api/chat.postMessage',
            params=dict(
                token=TOKEN,
                channel=cid,
                text=text,
                parse='full',
                as_user='true'))

def handle_join(event):
    uid = event['user']['id']
    resp = requests.post('https://slack.com/api/im.open',
            params=dict(
                token=TOKEN,
                user=uid)).json()
    cid = resp['channel']['id']
    send_message(cid, MESSAGE)

def handle_message(event):
    def should_parse_urls(event):
        global _self_uid
        return (
            event['user'] != _self_uid and
            event.get('subtype', None) in
                (None, 'me_message')
        )

    if should_parse_urls(event):
        cid = event['channel']
        slack_urls = extract_slack_urls(event['text'])

        redirects = []

        for slack_url in slack_urls:
            req = requests.get(slack_url.transformed)
            final_url = req.url
            if not is_human_equal(slack_url.transformed, final_url):
                redirects.append("{url} redirects to {final_url}".format(
                    url=slack_url.original, final_url=final_url))

        if redirects:
            notice = "Redirection notice: {}".format(", ".join(redirects))
            send_message(cid, notice)

def start_rtm():
    """Connect to slack and initiate socket handshake; returns JSON response"""
    resp = requests.post("https://slack.com/api/rtm.start",
            params=dict(
                token=TOKEN),
            verify=False)
    return resp.json()

EVENT_HANDLERS = {
    'team_join': handle_join,
    'message': handle_message,
}

def on_message(ws, message):
    event = json.loads(message)
    handler = EVENT_HANDLERS.get(event['type'])
    if handler:
        handler(event)

def on_error(ws, error):
    print "SOME ERROR HAS HAPPENED", error

def on_close(ws):
    print '\033[91m'+"Connection Closed"+'\033[0m'

def on_open(ws):
    print "Connection Started - Auto Greeting new joiners to the network"

if __name__ == "__main__":
    rtm_resp = start_rtm()
    _self_uid = rtm_resp['self']['id']
    ws = websocket.WebSocketApp(rtm_resp['url'],
                                on_message=on_message,
                                on_error=on_error,
                                on_close=on_close)
    #ws.on_open
    #ssl_defaults = ssl.get_default_verify_paths()
    ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
<commit_msg>on_xxx -> on_ws_xxx<commit_after>import websocket
import json
import requests
import os
import ssl
from collections import namedtuple
import re
import urlparse

###VARIABLES THAT YOU NEED TO SET MANUALLY IF NOT ON HEROKU#####
try:
	MESSAGE = os.environ['WELCOME-MESSAGE']
	TOKEN = os.environ['SLACK-TOKEN']
except:
	MESSAGE = 'Manually set the Message if youre not running through heroku or have not set vars in ENV'
	TOKEN = 'Manually set the API Token if youre not running through heroku or have not set vars in ENV'
###############################################################

_self_uid = None

SlackURL = namedtuple('SlackURL', ['original', 'transformed'])

def normalize_url_human(url):
    """
    >>> normalize_url_human("http://www.google.com").geturl()
    '//google.com'
    >>> normalize_url_human("https://google.com").geturl()
    '//google.com'
    >>> normalize_url_human("https://google.com/").geturl()
    '//google.com'
    >>> normalize_url_human("https://google.com/derp").geturl()
    '//google.com/derp'
    """

    parsed_url = urlparse.urlparse(url)
    dict_ = parsed_url._asdict()
    dict_['scheme'] = ""
    dict_['netloc'] = dict_['netloc'][4:] if dict_['netloc'].startswith("www.") else dict_['netloc']
    dict_['path'] = "" if dict_['path'] == "/" else dict_['path']

    return urlparse.ParseResult(**dict_)

def is_human_equal(url1, url2):
    """
    >>> is_human_equal("http://google.com/", "http://google.com/")
    True
    >>> is_human_equal("http://google.com/", "https://google.com/")
    True
    >>> is_human_equal("http://google.com/", "http://bing.com/")
    False
    >>> is_human_equal("http://google.com/", "http://www.google.com/")
    True
    >>> is_human_equal("http://google.com", "http://google.com/")
    True
    """

    return normalize_url_human(url1) == normalize_url_human(url2)

def extract_slack_urls(message):
    """
    >>> extract_slack_urls("derp <http://google.com|google.com> herp")
    [SlackURL(original='google.com', transformed='http://google.com')]
    >>> extract_slack_urls("derp <http://google.com|google.com> <http://bing.com|bing.com> herp")
    [SlackURL(original='google.com', transformed='http://google.com'), SlackURL(original='bing.com', transformed='http://bing.com')]
    >>> extract_slack_urls("derp <http://bit.ly/installfreemyapps> herp")
    [SlackURL(original='http://bit.ly/installfreemyapps', transformed='http://bit.ly/installfreemyapps')]
    >>> extract_slack_urls("derp google.com herp")
    []
    """

    def slack_url(wrapped_url):
        if '|' in wrapped_url:
            transformed_url, original_url = wrapped_url.split('|', 1)
        else:
            transformed_url = original_url = wrapped_url

        return SlackURL(original_url, transformed_url)

    wrapped_urls = re.findall(r'<(http[^>]+)>', message)

    return [slack_url(wrapped_url) for wrapped_url in wrapped_urls]

def send_message(cid, text):
    return requests.post('https://slack.com/api/chat.postMessage',
            params=dict(
                token=TOKEN,
                channel=cid,
                text=text,
                parse='full',
                as_user='true'))

def handle_join(event):
    uid = event['user']['id']
    resp = requests.post('https://slack.com/api/im.open',
            params=dict(
                token=TOKEN,
                user=uid)).json()
    cid = resp['channel']['id']
    send_message(cid, MESSAGE)

def handle_message(event):
    def should_parse_urls(event):
        global _self_uid
        return (
            event['user'] != _self_uid and
            event.get('subtype', None) in
                (None, 'me_message')
        )

    if should_parse_urls(event):
        cid = event['channel']
        slack_urls = extract_slack_urls(event['text'])

        redirects = []

        for slack_url in slack_urls:
            req = requests.get(slack_url.transformed)
            final_url = req.url
            if not is_human_equal(slack_url.transformed, final_url):
                redirects.append("{url} redirects to {final_url}".format(
                    url=slack_url.original, final_url=final_url))

        if redirects:
            notice = "Redirection notice: {}".format(", ".join(redirects))
            send_message(cid, notice)

def start_rtm():
    """Connect to slack and initiate socket handshake; returns JSON response"""
    resp = requests.post("https://slack.com/api/rtm.start",
            params=dict(
                token=TOKEN),
            verify=False)
    return resp.json()

EVENT_HANDLERS = {
    'team_join': handle_join,
    'message': handle_message,
}

def on_ws_message(ws, message):
    event = json.loads(message)
    handler = EVENT_HANDLERS.get(event['type'])
    if handler:
        handler(event)

def on_ws_error(ws, error):
    print "SOME ERROR HAS HAPPENED", error

def on_ws_close(ws):
    print '\033[91m'+"Connection Closed"+'\033[0m'

def on_ws_open(ws):
    print "Connection Started - Auto Greeting new joiners to the network"

if __name__ == "__main__":
    rtm_resp = start_rtm()
    _self_uid = rtm_resp['self']['id']
    ws = websocket.WebSocketApp(rtm_resp['url'],
                                on_message=on_ws_message,
                                on_error=on_ws_error,
                                on_close=on_ws_close)
    #ws.on_open
    #ssl_defaults = ssl.get_default_verify_paths()
    ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
<|endoftext|>


<commit_before>from os import path
import socket
import ssl
import sys

import commands
import config
import log
import utils
import zirc

here = path.dirname(path.abspath(__file__))

class Bot(zirc.Client):
    def __init__(self):
        self.userdb = {}
        # zIRC
        self.connection = zirc.Socket(family=socket.AF_INET6,
                                      wrapper=ssl.wrap_socket)
        self.config = zirc.IRCConfig(host="chat.freenode.net",
                                     port=6697,
                                     nickname="zIRCBot2",
                                     ident="zirc",
                                     realname="A zIRC bot",
                                     channels=config.channels,
                                     caps=config.caps)
        self.ctcp = {
            'VERSION': utils.version,
            'TIME': __import__('time').localtime(),
            'FINGER': "Don't finger me",
            'USERINFO': 'An IRC bot built using zIRC on Python',
            'SOURCE': 'https://github.com/wolfy1339/Python-IRC-Bot'
        }
        self.connect(self.config, certfile=path.join(here, "user.pem"))
        self.start()

    # Non-numeric events
    @staticmethod
    def on_all(event, irc):
        if event.raw.startswith("ERROR"):
            log.error(" ".join(event.arguments))
        else:
            if event.raw.find("%") == -1:
                log.debug(event.raw)

    @staticmethod
    def on_ctcp(irc, event, raw):
        log.info("Received CTCP reply " + raw)

    def on_privmsg(self, event, irc, arguments):
        if " ".join(arguments).startswith(config.commandChar):
            utils.call_command(self, event, irc, arguments)

    @staticmethod
    def on_send(data):
        if data.find("%") == -1:
            log.debug(data)

    def on_nick(self, event, irc):
        nick = event.source.nick
        to_nick = event.target
        for chan in self.userdb.values():
            for u in chan.values():
                if u['host'] == event.source.host:
                    self.userdb[chan][to_nick] = self.userdb[chan][nick]
                    del self.userdb[chan][nick]

    def on_quit(self, event, irc):
        nick = event.source.nick
        if nick == self.config['nickname']:
            sys.exit(1)
        else:
            for chan in self.userdb.values():
                for u in chan.values():
                    if u['host'] == event.source.host:
                        del self.userdb[chan][nick]

    def on_kick(self, event, irc):
        nick = event.raw.split(" ")[3]
        if nick == self.config['nickname']:
            log.warning("Kicked from %s, trying to re-join", event.target)
            irc.join(event.target)
        else:
            try:
                del self.userdb[event.target][nick]
            except KeyError:
                for i in self.userdb[event.target].values():
                    if i['host'] == event.source.host:
                        del self.userdb[event.target][i['hostmask'].split("!")[0]]

    def on_part(self, event, irc):
        requested = "".join(event.arguments).startswith("requested")
        if event.source.nick == self.config['nickname']:
            if requested:
                log.warning("Removed from %s, trying to re-join", event.target)
                irc.join(event.target)
            else:
                try:
                    del self.userdb[event.target][nick]
                except KeyError:
                    for i in self.userdb[event.target].values():
                        if i['host'] == event.source.host:
                            del self.userdb[event.target][i['hostmask'].split("!")[0]]
        else:
            try:
                del self.userdb[event.target][event.source.nick]
            except KeyError:
                for i in self.userdb[event.target].values():
                    if i['host'] == event.source.host:
                        del self.userdb[event.target][i['hostmask'].split("!")[0]]

    def on_join(self, event, irc):
        if event.source.nick == self.config['nickname']:
            log.info("Joining %s", event.target)
            irc.send("WHO {0} nuhs%nhuac".format(event.target))
        else:
            irc.send("WHO {0} nuhs%nhuac".format(event.source.nick))

    @staticmethod
    def on_invite(event, irc):
        if utils.checkPerms(event.source.host, trusted=True):
            hostmask = event.source.host
            log.info("Invited to %s by %s", event.arguments[1], hostmask)
            irc.join(event.arguments[1])

    # Numeric events
    def on_nicknameinuse(self, event, irc):
        log.error("Nick already in use, trying alternative")
        irc.nick(self.config['nickname'] + "_")

    @staticmethod
    def on_bannedfromchan(event, irc):
        s = event.raw.split(" ")
        channel = s[3]
        irc.notice("wolfy1339", "Banned from {0}".format(channel))
        log.warning("Banned from %s", channel)

    @staticmethod
    def on_endofmotd(event, irc):
        log.info("Received MOTD from network")

    @staticmethod
    def on_welcome(event, irc):
        log.info("Connected to network")

    def on_whoreply(self, event, irc):
        (ident, host, nick) = event.arguments[1:3] + event.arguments[4:5]
        channel = event.arguments[0]
        hostmask = "{0}!{1}@{2}".format(nick, ident, host)
        if nick != "ChanServ":
            try:
                self.userdb[channel][nick] = {
                    'hostmask': hostmask,
                    'host': host,
                    'account': host.split("/")[-1]
                }
            except KeyError:
                self.userdb[channel] = {}
                self.userdb[channel][nick] = {
                    'hostmask': hostmask,
                    'host': host,
                    'account': host.split("/")[-1]
                }

    def on_whospcrpl(self, event, irc):
        (ident, host, nick) = event.arguments[1:4]
        hostmask = "{0}!{1}@{2}".format(nick, ident, host)
        channel = event.arguments[0]
        account = event.arguments[4]
        if nick != "ChanServ":
            try:
                self.userdb[channel][nick] = {
                    'hostmask': hostmask,
                    'host': host,
                    'account': account if account != "0" else None
                }
            except KeyError:
                self.userdb[channel] = {}
                self.userdb[channel][nick] = {
                    'hostmask': hostmask,
                    'host': host,
                    'account': account if account != "0" else None
                }

    @staticmethod
    def on_315(event, irc):
        log.info("Received end of WHO reply from network")

Bot()
<commit_msg>Add handler for when nick is unavailabale<commit_after>from os import path
import socket
import ssl
import sys

import commands
import config
import log
import utils
import zirc

here = path.dirname(path.abspath(__file__))

class Bot(zirc.Client):
    def __init__(self):
        self.userdb = {}
        # zIRC
        self.connection = zirc.Socket(family=socket.AF_INET6,
                                      wrapper=ssl.wrap_socket)
        self.config = zirc.IRCConfig(host="chat.freenode.net",
                                     port=6697,
                                     nickname="zIRCBot2",
                                     ident="zirc",
                                     realname="A zIRC bot",
                                     channels=config.channels,
                                     caps=config.caps)
        self.ctcp = {
            'VERSION': utils.version,
            'TIME': __import__('time').localtime(),
            'FINGER': "Don't finger me",
            'USERINFO': 'An IRC bot built using zIRC on Python',
            'SOURCE': 'https://github.com/wolfy1339/Python-IRC-Bot'
        }
        self.connect(self.config, certfile=path.join(here, "user.pem"))
        self.start()

    # Non-numeric events
    @staticmethod
    def on_all(event, irc):
        if event.raw.startswith("ERROR"):
            log.error(" ".join(event.arguments))
        else:
            if event.raw.find("%") == -1:
                log.debug(event.raw)

    @staticmethod
    def on_ctcp(irc, event, raw):
        log.info("Received CTCP reply " + raw)

    def on_privmsg(self, event, irc, arguments):
        if " ".join(arguments).startswith(config.commandChar):
            utils.call_command(self, event, irc, arguments)

    @staticmethod
    def on_send(data):
        if data.find("%") == -1:
            log.debug(data)

    def on_nick(self, event, irc):
        nick = event.source.nick
        to_nick = event.target
        for chan in self.userdb.values():
            for u in chan.values():
                if u['host'] == event.source.host:
                    self.userdb[chan][to_nick] = self.userdb[chan][nick]
                    del self.userdb[chan][nick]

    def on_quit(self, event, irc):
        nick = event.source.nick
        if nick == self.config['nickname']:
            sys.exit(1)
        else:
            for chan in self.userdb.values():
                for u in chan.values():
                    if u['host'] == event.source.host:
                        del self.userdb[chan][nick]

    def on_kick(self, event, irc):
        nick = event.raw.split(" ")[3]
        if nick == self.config['nickname']:
            log.warning("Kicked from %s, trying to re-join", event.target)
            irc.join(event.target)
        else:
            try:
                del self.userdb[event.target][nick]
            except KeyError:
                for i in self.userdb[event.target].values():
                    if i['host'] == event.source.host:
                        del self.userdb[event.target][i['hostmask'].split("!")[0]]

    def on_part(self, event, irc):
        requested = "".join(event.arguments).startswith("requested")
        if event.source.nick == self.config['nickname']:
            if requested:
                log.warning("Removed from %s, trying to re-join", event.target)
                irc.join(event.target)
            else:
                try:
                    del self.userdb[event.target][nick]
                except KeyError:
                    for i in self.userdb[event.target].values():
                        if i['host'] == event.source.host:
                            del self.userdb[event.target][i['hostmask'].split("!")[0]]
        else:
            try:
                del self.userdb[event.target][event.source.nick]
            except KeyError:
                for i in self.userdb[event.target].values():
                    if i['host'] == event.source.host:
                        del self.userdb[event.target][i['hostmask'].split("!")[0]]

    def on_join(self, event, irc):
        if event.source.nick == self.config['nickname']:
            log.info("Joining %s", event.target)
            irc.send("WHO {0} nuhs%nhuac".format(event.target))
        else:
            irc.send("WHO {0} nuhs%nhuac".format(event.source.nick))

    @staticmethod
    def on_invite(event, irc):
        if utils.checkPerms(event.source.host, trusted=True):
            hostmask = event.source.host
            log.info("Invited to %s by %s", event.arguments[1], hostmask)
            irc.join(event.arguments[1])

    # Numeric events
    def on_unavailresource(self, event, irc):
        log.error("Nick unavailable, trying alternative")
        irc.nick(self.config['nickname'] + "_")
        self.config['nickname'] = self.config['nickname'] + "_"

    def on_nicknameinuse(self, event, irc):
        log.error("Nick already in use, trying alternative")
        irc.nick(self.config['nickname'] + "_")
        self.config['nickname'] = self.config['nickname'] + "_"

    @staticmethod
    def on_bannedfromchan(event, irc):
        s = event.raw.split(" ")
        channel = s[3]
        irc.notice("wolfy1339", "Banned from {0}".format(channel))
        log.warning("Banned from %s", channel)

    @staticmethod
    def on_endofmotd(event, irc):
        log.info("Received MOTD from network")

    @staticmethod
    def on_welcome(event, irc):
        log.info("Connected to network")

    def on_whoreply(self, event, irc):
        (ident, host, nick) = event.arguments[1:3] + event.arguments[4:5]
        channel = event.arguments[0]
        hostmask = "{0}!{1}@{2}".format(nick, ident, host)
        if nick != "ChanServ":
            try:
                self.userdb[channel][nick] = {
                    'hostmask': hostmask,
                    'host': host,
                    'account': host.split("/")[-1]
                }
            except KeyError:
                self.userdb[channel] = {}
                self.userdb[channel][nick] = {
                    'hostmask': hostmask,
                    'host': host,
                    'account': host.split("/")[-1]
                }

    def on_whospcrpl(self, event, irc):
        (ident, host, nick) = event.arguments[1:4]
        hostmask = "{0}!{1}@{2}".format(nick, ident, host)
        channel = event.arguments[0]
        account = event.arguments[4]
        if nick != "ChanServ":
            try:
                self.userdb[channel][nick] = {
                    'hostmask': hostmask,
                    'host': host,
                    'account': account if account != "0" else None
                }
            except KeyError:
                self.userdb[channel] = {}
                self.userdb[channel][nick] = {
                    'hostmask': hostmask,
                    'host': host,
                    'account': account if account != "0" else None
                }

    @staticmethod
    def on_315(event, irc):
        log.info("Received end of WHO reply from network")

Bot()
<|endoftext|>