예제 #1
0
def set_chat_id(email, tgname, chat_id):

    try:
        profile = None
        log.info(
            f"set chat id email: {email} tgname: {tgname} chat_id: {chat_id}")
        # find profile
        if email:
            # do not use tgname in this search!
            profile = Profile.objects.get(user__email=email)
        else:
            if tgname:
                # case-insensitive search for telegram_name
                profile = Profile.objects.get(telegram_name__iexact=tgname)
            else:
                profile = Profile.objects.get(telegram_name=str(chat_id))

        log.info(f"got profile: {profile}")

        # verify profile
        if profile.telegram_name.lower() != tgname.lower(
        ) and profile.telegram_name != str(chat_id):
            if tgname:
                return 'Set telegram name {} in profile'.format(tgname)
            else:
                return 'Set telegram name {} in profile'.format(chat_id)

        rs = RemoteServer(ci=profile.ci)
        if tgname:
            jr = rs.api_admin_tglink(email, tgname, chat_id)
        else:
            jr = rs.api_admin_tglink(email, chat_id, chat_id)

        r = json.loads(jr)

        # sync if needed
        if rs.ci != myci():
            for username in r['sync']:
                data = rs.get_user(username)
                ie = Impex()
                ie.set_verbosity(0)
                ie.preimport_cleanup(data)
                ie.import_data(data)

        return r['msg']

    except Profile.DoesNotExist as e:
        log.info('Not found profile for tg user {}. Try little later?'.format(
            tgname))
        if tgname:
            return "Telegram user with name '{}' not known in Okerr. Sorry. Please set this name in okerr profile first and try little later.".format(
                tgname)
        else:
            return "Telegram user with id {} not known in Okerr. Sorry. Please set this id in okerr profile first and try little later.".format(
                chat_id)

    except Profile.MultipleObjectsReturned as e:
        log.error('Multiple profiles for tg user {}'.format(tgname))
        return "More then one telegram user '{}' in Okerr. Use /on <email> command.".format(
            tgname)
예제 #2
0
    def sync(self, url, overwrite=True):    

        rs = RemoteServer(url = url)

        User = get_user_model()
        Profile = self.get_model('Profile')
        
        
        ci = myci()
        rci = rs.get_ci()
        
        userlist = rs.get_userlist()

        for email in userlist:
            if not email:
                continue
            log.info('sync user {} from {} rci: {}'.format(email, url2host(url), rci))
            self.vprint(2, 'sync user {} from {}'.format(email, url2host(url)))            
            profile = None
            
            # get local user
            try:
                profile = Profile.objects.get(user__email=email)
                                
                if profile.ci == ci and not overwrite:
                    log.error('sync: user {} ci: {} is mine!!'.format(email, ci))
                    raise Exception('user: {} ci: {} is mine and not overwrite!'.format(email, ci))                            
            except User.DoesNotExist:
                pass
            except Profile.DoesNotExist:
                # no profile. okay. we will re-create it. it's safe - we dont have profile anyway
                pass
            
            try:
                data = rs.get_user(email)
            except (requests.exceptions.RequestException, RemoteServerExc) as e:
                log.warning('sync error (user {} from {}): {}'.format(email, rs.name, str(e)))
                continue

            # delete this user before importing
            if profile:
                if overwrite:
                    # log.debug("ZZZ luser.delete (profile: {})".format(profile))
                    profile.predelete()
                    profile.delete()
                else:
                    # do not import this user, because it's local and not overwrite
                    continue

            #log.debug("ZZZ import data")
            self.import_data(data)

        self.delete_deleted(rs)
예제 #3
0
    def syncmap(cls, hostname=None):

        if hostname is None:
            hostname = settings.HOSTNAME

        if not settings.SYNC_MAP:
            # None or empty dict
            return

        if not hostname in settings.SYNC_MAP:
            log.error('No {} in SYNC_MAP'.format(hostname))
            return


        ie = Impex()
        ie.set_verbosity(0)

        for rsname in settings.SYNC_MAP[hostname]:            
            
            rs = RemoteServer(name = rsname)
            try:
                log.info('syncmap from {} {}'.format(rsname, url2host(rs.url)))
                ie.sync(rs.url)
            except Exception as e:
                log.error('syncmap exception {}: {} {}: {}'.format(url2host(rsname), type(e), str(e), traceback.format_exc()))
예제 #4
0
def setci_remote(email,ci):    
    
    me = RemoteServer.me()
    for rs in me.all_other():
        if rs.is_net():
            print(("update to rs {}: {}".format(rs.name, rs.url)))
            try:
                rs.set_ci(ci, email)
            except requests.exceptions.RequestException as e:
                print("FAILED: {}".format(str(e)))
예제 #5
0
    def reinit(self):
        # no need to reinit anything in db
        app_model = oauth2_provider.models.get_application_model()

        if not hasattr(settings, 'OAUTH2_CLIENTS'):
            print(
                "skip reinit OAUTH2 because not configured (usually this is OK)"
            )
            return

        User = get_user_model()
        app_model.objects.all().delete()

        appd = settings.OAUTH2_CLIENTS

        print("appd:", appd)

        app = app_model()
        app.user = None
        for f in self.fields:
            setattr(app, f, appd[f])

        # generate redirect_uris
        redirect_uris = ''

        # allsrv = settings.CLUSTER + ['cp.okerr.com']

        for rs in RemoteServer.all_rs():
            url = rs.url + 'oauth2/callback'
            print("add cluster url:", url)
            redirect_uris += url + '\r\n'

        #if hasattr(settings, 'OAUTH2_REDIRECT_URI'):
        #    for url in settings.OAUTH2_REDIRECT_URI:
        #        print("add custom url:", url)
        #        redirect_uris += url + '\r\n'

        app.redirect_uris = redirect_uris
        app.save()
예제 #6
0
def unset_chat_id(chat_id):
    try:
        for rs in RemoteServer.all_rs():
            rs.api_admin_tglink(chat_id=chat_id)
    except Exception as e:
        print(e)
예제 #7
0
def cmd_qsum(update, ctx):
    bot = ctx.bot
    args = ctx.args

    reg_command(update, ctx)
    reported = 0
    projects = list()

    if len(args):
        textid = args[0]
    else:
        textid = None

    chat_id = update.message.chat_id

    if textid:
        project = Project.get_by_textid(textid)
        if project is None:
            bot.send_message(chat_id=chat_id, text="No such project")
            return

        # has access?
        access = False
        for profile in Profile.objects.filter(telegram_chat_id=chat_id):
            if project.member(profile.user):
                access = True

        if access:
            projects.append(project)
        else:
            bot.send_message(chat_id=chat_id, text="No such project")
            return

    else:
        log.info('list all projects for #{}'.format(chat_id))
        try:
            # all available projects
            for profile in Profile.objects.filter(telegram_chat_id=chat_id):
                for p in profile.projects():
                    if not p in projects:
                        projects.append(p)
        except Exception as e:
            log.error('exc: {}'.format(e))

        log.info("will list {} projects".format(len(projects)))

    if not projects:
        log.info("no projects!")
        bot.send_message(chat_id=chat_id,
                         text="No projects",
                         reply_markup=get_reply_markup(chat_id))
        return

    for p in projects:
        rs = RemoteServer(ci=p.ci)
        data = rs.api_admin_qsum(p.get_textid())
        log.info("show project {}".format(p.get_textid()))

        #msg = 'zzzzz'
        tpl = u'''
Project *{}* ({})
Total {} (maintenance: {}, silent: {}, ERR: {})
'''
        if data is None:
            log.error('api_admin_qsum for {} / {} returned None'.format(
                rs.name, p.get_textid()))
            bot.send_message(
                chat_id=chat_id,
                parse_mode=telegram.ParseMode.MARKDOWN,
                reply_markup=get_reply_markup(chat_id),
                text=
                'Server {} for project {} unavailable at moment. Sorry. Try again later.'
                .format(rs.name, p.get_textid()))
            return

        msg = tpl.format(data['project'], data['textid'], data['cnt']['total'],
                         data['cnt']['maintenance'], data['cnt']['silent'],
                         data['cnt']['ERR'])

        for i in data['ERR'][:5]:
            try:
                link = rs.reverse('okerr:ilocator', {
                    'pid': data['textid'],
                    'iid': i['name']
                })
                msg += u'[{}]({}) = {} ({}) {} ago\n'.format(
                    md_escape(i['name']), link, i['status'],
                    md_escape(i['details']), i['age'])
            except Exception as e:
                print(e)

        if len(data['ERR']) > 5:
            msg += '(Only first 5 of {} shown)\n'.format(len(data['ERR']))

        bot.send_message(chat_id=chat_id,
                         parse_mode=telegram.ParseMode.MARKDOWN,
                         reply_markup=get_reply_markup(chat_id),
                         text=msg)
예제 #8
0
def main():
    #global updater, log
    global log
    global bot
    global main_rs

    started = datetime.datetime.now()

    try:
        def_server = getattr(settings, 'SERVER_URL')
    except AttributeError:
        def_server = None

    parser = argparse.ArgumentParser(description='okerr telegram server.')
    parser.add_argument('-s',
                        '--server',
                        default=def_server,
                        help='Remote okerr server URL')
    parser.add_argument('-v',
                        dest='verbose',
                        action='store_true',
                        default=False,
                        help='verbose mode')

    args = parser.parse_args()

    assert (settings.TGBOT_TOKEN)

    main_rs = RemoteServer(url=args.server)
    assert (main_rs)
    signal.signal(signal.SIGINT, sighandler)

    #logging.basicConfig(
    #    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    #    level=logging.DEBUG)

    log = logging.getLogger('okerr-telebot')
    out = logging.StreamHandler(sys.stdout)
    out.setFormatter(
        logging.Formatter('%(asctime)s %(message)s',
                          datefmt='%Y/%m/%d %H:%M:%S'))
    out.setLevel(logging.INFO)

    log.addHandler(out)

    err = logging.StreamHandler(sys.stderr)
    err.setLevel(logging.ERROR)
    log.addHandler(err)

    if args.verbose:
        log.setLevel(logging.DEBUG)
    else:
        log.setLevel(logging.INFO)

    log.propagate = False

    op.setlog(log)

    log.info("Start polling (pid: {} started: {})...".format(
        os.getpid(), started.strftime("%Y/%m/%d %H:%M:%S")))

    # updater.start_polling()

    bot.infinity_polling()
    log.error("END OF INFINITY (pid: {} now: {} age: {})".format(
        os.getpid(),
        datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S"),
        (datetime.datetime.now() - started)))
    """
예제 #9
0
def cmd_qsum(message):

    reg_command(message)
    reported = 0
    projects = list()

    chat_id = message.chat.id

    username = main_rs.api_admin_chat_id(chat_id)
    if username is None:
        tgname = message.from_user.username
        error_msg = "chat id: {} tg name: {} not linked to any account".format(
            chat_id, tgname)
        log.info(error_msg)
        bot.send_message(chat_id=chat_id,
                         text=error_msg,
                         reply_markup=get_reply_markup(chat_id))
        return

    project_list = main_rs.api_admin_member(username)
    if project_list is None:
        log.info('Failed to get project list for user {} from {}'.format(
            username, main_rs))
        bot.send_message(chat_id=chat_id,
                         text="Internal exception, please contact support",
                         reply_markup=get_reply_markup(chat_id))
        return

    for textid in project_list:
        projects.append(textid)

    if not projects:
        log.info("no projects!")
        bot.send_message(chat_id=chat_id,
                         text="No projects",
                         reply_markup=get_reply_markup(chat_id))
        return

    for textid in projects:
        url = main_rs.api_director(textid)
        rs = RemoteServer(url=url)
        data = rs.api_admin_qsum(textid)
        log.info("show project {}".format(textid))

        #msg = 'zzzzz'
        tpl = '''
Project *{}* ({})
Total {} (maintenance: {}, silent: {}, ERR: {})
'''
        if data is None:
            log.error('api_admin_qsum for {} / {} returned None'.format(
                rs.name, p.get_textid()))
            bot.send_message(
                chat_id=chat_id,
                parse_mode="Markdown",
                reply_markup=get_reply_markup(chat_id),
                text=
                'Server {} for project {} unavailable at moment. Sorry. Try again later.'
                .format(rs.name, p.get_textid()))
            return

        msg = tpl.format(data['project'], data['textid'], data['cnt']['total'],
                         data['cnt']['maintenance'], data['cnt']['silent'],
                         data['cnt']['ERR'])

        for i in data['ERR'][:5]:
            try:
                link = rs.reverse('okerr:ilocator', {
                    'pid': data['textid'],
                    'iid': i['name']
                })
                msg += '[{}]({}) = {} ({}) {} ago\n'.format(
                    md_escape(i['name']), link, i['status'],
                    md_escape(i['details']), i['age'])
            except Exception as e:
                print(e)

        if len(data['ERR']) > 5:
            msg += '(Only first 5 of {} shown)\n'.format(len(data['ERR']))

        bot.send_message(chat_id=chat_id,
                         parse_mode="Markdown",
                         reply_markup=get_reply_markup(chat_id),
                         text=msg)
예제 #10
0
def cmd_recheck(message):
    reg_command(message)
    projects = list()

    chat_id = message.chat.id

    username = main_rs.api_admin_chat_id(chat_id)
    if username is None:
        tgname = message.from_user.username
        error_msg = "chat id: {} tg name: {} not linked to any account".format(
            chat_id, tgname)
        log.info(error_msg)
        bot.send_message(chat_id=chat_id,
                         text=error_msg,
                         reply_markup=get_reply_markup(chat_id))
        return

    project_list = main_rs.api_admin_member(username)
    if project_list is None:
        log.info('Failed to get project list for user {} from {}'.format(
            username, main_rs))
        bot.send_message(chat_id=chat_id,
                         text="Internal exception, please contact support",
                         reply_markup=get_reply_markup(chat_id))
        return

    for textid in project_list:
        projects.append(textid)

    if not projects:
        log.info("no projects!")
        bot.send_message(chat_id=chat_id,
                         text="No projects",
                         reply_markup=get_reply_markup(chat_id))
        return

    for textid in projects:
        url = main_rs.api_director(textid)
        rs = RemoteServer(url=url)

        l = rs.api_recheck(textid)

        if l is None:
            log.error('api_recheck for {} / {} returned None'.format(
                rs.name, p.get_textid()))
            bot.send_message(
                chat_id=chat_id,
                parse_mode="Markdown",
                reply_markup=get_reply_markup(chat_id),
                text=
                'Server {} for project {} unavailable at moment. Sorry. Try again later.'
                .format(rs.name, p.get_textid()))
            return

        log.info("rechecked project {}: {} indicators".format(textid, len(l)))

        if l:
            # not empty list
            msg = "Project {}: recheck: {}".format(textid, ' '.join(l[:5]))
        else:
            msg = "Project {}: nothing to recheck".format(textid)

        bot.send_message(chat_id=chat_id,
                         parse_mode="Markdown",
                         reply_markup=get_reply_markup(chat_id),
                         text=msg)
예제 #11
0
    def handle(self, *args, **options):
        #print "options:",options
        
        user = None
        profile = None

        if options['verbosity'] >= 1:
            log = logging.getLogger('okerr')
            log.setLevel(logging.DEBUG)
            log.addHandler(logging.StreamHandler())

        # prepare data
        try:
            if options['user'] and not options['clone']:
                email = options['user']
                user = User.objects.get(email=options['user'])
                profile = user.profile
        except User.DoesNotExist:
            print("No such user")
        except Profile.DoesNotExist:
            print("No such profile")
    

        if options['dblog']:
            l = logging.getLogger('django.db.backends')
            l.setLevel(logging.DEBUG)
            l.addHandler(logging.StreamHandler())
                

        if options['skip']:
            for s in options['skip']:
                RemoteServer.skip(s)


        if options['hostinfo']:
            if options['hostinfo'] == 'all':
                rs = RemoteServer.me()
                for rrs in rs.all_rs():
                    print("== Hostinfo for %s" % rrs)
                    print(rrs.hostinfo())
                
            else:
                rs = RemoteServer(name = options['hostinfo'])
                print(rs.hostinfo())
            return

        if options['cluster']:
            print(json.dumps(settings.MACHINES, indent=4))                           
            return

        if options['compare']:
            ul = dict()
            users = list()
            badusers = list()
            me = RemoteServer.me()
            for rs in me.all_rs():
                ul[rs.name] = rs.list()
            
            for ulist in list(ul.values()):
                for u in ulist:
                    email = u['user']
                    if not email in users:
                        users.append(email)



            mnames = sorted(ul.keys())
            fmt = "{:<50}|{:1}| " + "{:<15}| " * (len(mnames))                        
            
            titles = list()
            for m in mnames:
                rs = RemoteServer(name = m)
                print(rs, rs.ci)
                titles.append("{} ({})".format(rs.name, rs.ci))
            print(fmt.format('EMAIL','X', *titles))
            print(fmt.format('-'*50,'-',*["-"*15 for x in range(len(mnames))]))
            
            
            for username in users:
                cil = list()
                for m in mnames:                    
                    urec = [urec for urec in ul[m] if urec['user'] == username]
                    if urec:
                        cil.append(urec[0]['ci'])
                    else:
                        cil.append('-')
            
                if cil[1:] == cil[:-1]:
                    cil.insert(0,'')
                    if options['verbosity']>=1:
                        print(fmt.format(username, *cil))
                else:
                    cil.insert(0,'X')
                    print(fmt.format(username, *cil))
                    
            

            return


        if options['reanimate']:
            if profile:
                print("single reanimate", profile)
                profile.reanimate()
            else:
                for p in Profile.objects.filter(ci = myci()):
                    print("reanimate",p)
                    p.reanimate()
            return

        if options['info']:
            print("Host: {} Cluster: {} ci: {}".format(repr(settings.HOSTNAME), repr(settings.CLUSTER_NAME), myci()))
            print("Profiles: {} / {}".format(Profile.objects.filter(ci=myci()).count(), Profile.objects.count()))
            return

        if options['list']:
            for p in Profile.objects.all():
                    print(p.ci, p.user.username)
        elif options['cilist'] is not None:
            for p in Profile.objects.filter(ci=options['cilist']).all():
                print(p.user.username)
        elif options['wipe']:
            if not (user or profile):
                print("need either user ({}) or profile ({})".format(user, profile))
            if user:
                user.delete()
            if profile:
                profile.delete()
            print("deleted")
        elif options['ciwipe'] is not None:
            if options['ciwipe'] == myci():
                print("cannot ciwipe for my own ci {}".format(myci()))
                return
            for p in Profile.objects.filter(ci=options['ciwipe']).all():
                if options['verbosity']>=1:
                    print("delete {} ci: {}".format(p, p.ci))
                p.user.delete()
                p.delete()
        elif options['otherciwipe']:
            ci = myci()
            for p in Profile.objects.all():
                if p.ci == ci:
                    if options['verbosity']>=1:
                        print("skip profile {} ci: {}".format(p, p.ci))
                else:
                    if options['verbosity']>=1:
                        print("delete {} ci: {}".format(p, p.ci))
                    p.user.delete()
                    p.delete()
        
        elif options['export']:
            if profile:
                handle_export(profile, options['file'], options['verbosity'])       
            else:
                print("Need --user")
 
        elif options['import']:
            data = get_content(filename = options['file'], url = options['url'], email = options['user'])
            if options['clone']:
                data = clone(data, options['user'])                        
            handle_import(data, options['overwrite'], options['verbosity'])
 
        elif options['sync']:
            handle_sync(options['sync'], options['overwrite'], options['verbosity'])
 
        elif options['syncmap']:            
                ie = Impex()
                ie.set_verbosity(options['verbosity'])
                ie.syncmap()
                return

        elif options['takeci'] is not None:            
            for profile in Profile.objects.filter(ci=options['takeci']):
                print("process profile", profile)
                ## profile = Profile.objects.get(user__email = options['user'])
                setci_local(profile, myci())
                if options['remote']:
                    setci_remote(profile.user.username, myci())
                else:
                    print("skip remote, because no --remote")
            return
            
        elif options['setci'] is not None:            
            if options['user']:
                profile = Profile.objects.get(user__email = options['user'])
                setci_local(profile, options['setci'])
                if options['remote']:
                    setci_remote(options['user'], options['setci'])
                else:
                    print("skip remote, because no --remote")
            else:
                print("need --user")
            return

        
        
            print("setci {} for user {}".format(options['setci'], email))
            # change for profile and projects
            ci = options['setci']
            
            profile.set_ci(options['setci'])
            profile.save()
        else:
            print("Whaat?")