Exemple #1
0
def save_mem():
    log.D('+ save memory to DB')
    module = sys.modules[ram.__name__]
    module_attrs = dir(module)
    variables = {
        key: getattr(module, key)
        for key in module_attrs
        if key[0] != '_' and not callable(getattr(module, key))
    }
    conn = None
    rows = []
    for var, val in variables.items():
        if isinstance(val, dict):
            val = {k: v for k, v in val.items() if v != set()}
        if isinstance(val, (C.Types.Datetime, C.Types.Timedelta)):
            val = str(val)
        rows.append((
            var,
            repr(val),
        ))
    try:
        conn = psycopg2.connect(C.DATABASE_URL, sslmode='require')
        cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        cur.execute("TRUNCATE TABLE memory RESTART IDENTITY")
        query = "INSERT INTO memory (var, val) VALUES (%s, %s)"
        cur.executemany(query, rows)
        conn.commit()
    except psycopg2.DatabaseError as e:
        log.E('<ev.save_mem>  DatabaseError %s' % e)
        # sys.exit(1)
    else:
        log.D('+ memory saved successfully')
    finally:
        if conn:
            conn.close()
Exemple #2
0
async def on_voice_state_update_u(before, after):
    """
    :type before: C.types.Member
    :type after: C.types.Member
    """
    global voice_alert_msg
    v_old = before.voice_channel
    v_new = after.voice_channel

    if v_new:
        on_user_life_signs(after.id)

    if v_old == v_new:
        return

    if v_old and v_new:
        log.I('<voice> {0} reconnects from #{1} to #{2}.'.format(
            after, v_old, v_new))
    elif v_old:
        log.I('<voice> {0} disconnects from #{1}.'.format(after, v_old))
    elif v_new:
        log.I('<voice> {0} connects to #{1}.'.format(after, v_new))
        note = com.voice_note(after)
        if note:
            log.D('<voice> Note event')
            await other.type2sent(after, note)

    await _del_voice_alert(after.id)
    user = None
    ch = None
    if (after.id in C.voice_alert
            and v_new) or (after.top_role > after.server.me.top_role):
        user = after
        ch = v_new  # type: C.Types.Channel
    elif v_old and v_old.voice_members and v_old.voice_members[
            0].id in C.voice_alert:
        user = v_old.voice_members[0]
        await _del_voice_alert(user.id)
        ch = v_old  # type: C.Types.Channel

    if user and ch and len(ch.voice_members) == 1 and not other.s_in_s(
        ('radio', 'радио'), ch.name.lower()):
        log.D('<voice> Event to @here')
        every_prm = ch.overwrites_for(ch.server.default_role)
        if every_prm.connect or (every_prm.connect is None and
                                 ch.server.default_role.permissions.connect):
            va_ids = voice_alert_ids.setdefault(user.id, [])
            va_msg = voice_alert_msg.setdefault(user.id, [])
            va_ids.append(
                com.write_msg(C.main_ch,
                              text=com.voice_event(user, ch),
                              save_obj=va_msg))
Exemple #3
0
def timer_quarter_h():
    global timer_quarter_works
    start_quarter_h_timer()
    try:
        log.D('+ Quarter hour timer event!')
        _timer_check_games()
        _timer_check_silence_in_chat()
        timer_quarter_works += 1
        save()
        if timer_quarter_works % TMR_IN_H == 0:  # hour_timer
            # other.later_coro(1, _timer_check_stuff())
            mn = 4
        else:
            mn = 1
        log.D('+ Timer event finished!')
        log.p('------------------------------------- ' * mn)
    except Exception as e:
        other.pr_error(e, 'timer_quarter_h')
Exemple #4
0
def save_texts_used():
    log.D('+ save data_used to DB')
    conn = None
    rows = [(i, val) for i, val in enumerate(com.d2u.data_used)]
    try:
        conn = psycopg2.connect(C.DATABASE_URL, sslmode='require')
        cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        cur.execute("TRUNCATE TABLE data_used RESTART IDENTITY")
        query = "INSERT INTO data_used (id, value) VALUES (%s, %s)"
        cur.executemany(query, rows)
        conn.commit()
    except psycopg2.DatabaseError as e:
        log.E('<ev.save_texts_used> DatabaseError %s' % e)
    else:
        log.D('+ data_used saved successfully')
    finally:
        if conn:
            conn.close()
Exemple #5
0
async def time_sync():
    # scan chat and get users time of last_message from history
    log.I('+ Time_sync start')
    t = {}
    mems = [mem.id for mem in C.vtm_server.members]
    for ch in C.vtm_server.channels:
        if str(ch.type) == 'text':
            t[ch.position] = ch
    channels = [t[k] for k in sorted(t)]
    log.D('- {0} channels prepare to scan:'.format(len(channels)))
    for i, ch in enumerate(channels):
        pr = ch.permissions_for(ch.server.me)
        if pr.read_message_history:
            log.D('+ {0}) {1} - check'.format(i + 1, ch.name))
            mems_i = set(mems)
            count = 0
            messes = []
            async for mess in C.client.logs_from(ch, limit=1000000):
                messes.append(mess)

            for mess in messes:
                aid = mess.author.id
                if aid in mems_i:
                    ts = other.get_sec_total(mess.timestamp)
                    if ts > usrs[aid].last_m:
                        usrs[aid].last_m = ts
                        usrs[aid].status = 'upd'

                    mems_i.remove(aid)
                    if len(mems_i) < 1:
                        break
                count += 1
                if count % 10000 == 0:
                    log.D('- - <time_sync> check messages: ', count,
                          ', mems_i: ', len(mems_i))
            log.D('+ {0}) {1} - done'.format(i + 1, ch.name))
        else:
            log.D('-- {0}) {1} - not permissions for reading'.format(
                i + 1, ch.name))
    log.I('+ Time_sync end')
    log.jD('Test results:')
    for mem in C.vtm_server.members:
        log.jD('{0} \t-\t {1}'.format(mem, other.sec2str(offtime(mem.id))))
Exemple #6
0
async def do_check_and_embrace(name, clan_name=None):
    user = other.find_member(C.vtm_server, name)
    roles = set(role.id for role in user.roles).difference(C.other_roles)
    if len(roles) == 1:
        await just_embrace(user, clan_name=clan_name)
        # just_embrace_say(user, clan_name)
        # text = await do_embrace(user, clan_name=clan_name)
        # com.write_msg(C.main_ch, text)
    else:
        log.D('<do_check_and_embrace> Will not embrace, there are other roles.')
Exemple #7
0
async def _rem_roles_coro(member, roles, error_msg='rem_roles'):
    log.D('Try rem roles ({r}) to @{m.display_name}.'.format(
        m=member, r=', '.join([r.name for r in roles])))
    try:
        await C.client.remove_roles(member, *roles)
        return True
    except C.Exceptions.Forbidden:
        log.jW("[{}] Bot can't change roles.".format(error_msg))
    except Exception as e:
        pr_error(e, error_msg, 'Error in changing roles')
    return False
Exemple #8
0
async def sync():
    # scan chat and get users array from messages in history
    log.I('+ Sync Start')
    count = 0
    # print('[{0}] TEST'.format(other.t2s()))
    for mem in C.client.get_all_members():
        distribute(mem)

    async for message in C.client.logs_from(C.main_ch, limit=1000000):
        distribute(message.author, other.get_sec_total(message.timestamp))
        count += 1
        if count % 10000 == 0:
            log.D('<sync> Check message: ', count)
        # for i in message.raw_mentions:
        #     distribute(await C.client.get_user_info(i), message.timestamp)

    for usr in bans:
        distribute(usr)
    log.D('<sync> MESS COUNT = {0}'.format(str(count)))
    rewrite()
    log.I('+ Sync End')
Exemple #9
0
async def tree_test():
    import re
    embr_txt = (
        '<@(?P<sir>\d+)> получает право на становление, и <@(?P<child>\d+)> теперь познает всю боль нежизни.',
        '<@(?P<sir>\d+)> дарует становление, но было ли получено разрешение, и что теперь ждёт новоявленое дитя <@('
        '?P<child>\d+)>?',
        '<@(?P<child>\d+)> теперь находится под защитой клана и теперь за ним присмотрит его сир, <@(?P<sir>\d+)>',
        'Не может быть, <@(?P<sir>\d+)> дарует становление неонату <@(?P<child>\d+)> - но является ли это наградой - '
        'или наказанием?',
        'Витэ капнуло тут раз - <@(?P<sir>\d+)> теперь... сир у нас. Что ты об этом думаешь, <@(?P<child>\d+)>?',
    )
    r_txt = []
    for txt in embr_txt:
        r_txt.append(re.compile(txt))
    ch = other.get_channel('flood')
    log.D('- <read> for {0}({1}) start'.format(ch, ch.id))
    messages = []
    count = 0
    async for message in C.client.logs_from(
            ch, limit=1000000000):  #type: C.Types.Message
        if message.author.id == C.users['bot'] and len(message.mentions) == 2:
            messages.append(message)
            count += 1
            if count % 100 == 0:
                log.D('- - <read> save messages: ', count)
    log.D('- <read> end save with {0} messages'.format(count))
    messages.reverse()
    log.D('- <read> start format messages')
    tree = {}
    for msg in messages:
        for r in r_txt:
            m = r.match(msg.content)
            if m:
                d = m.groupdict()
                tree[d['child']] = d['sir']
                log.D(msg.clean_content)
    log.I(tree)
    log.I(len(tree))
Exemple #10
0
def load(res=False):
    usrs_l = {}
    gone_l = {}
    conn = None
    if not res:
        log.D('- load people tables')
    try:
        conn = psycopg2.connect(C.DATABASE_URL, sslmode='require')
        cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        cur.execute("SELECT * FROM members")
        rows = cur.fetchall()
        for row in rows:  # type: dict
            u = Usr.load(row)
            usrs_l[u.id] = u

        cur.execute("SELECT * FROM users_gone")
        rows = cur.fetchall()
        for row in rows:  # type: dict
            g = Gn.load(row)
            gone_l[g.id] = g

    except psycopg2.DatabaseError as e:
        log.E('DatabaseError %s' % e)
        sys.exit(1)
    else:
        if not res:
            log.D('+ people tables loaded successfully')
    finally:
        if conn:
            conn.close()

    if res:
        return {'usrs': usrs_l, 'gone': gone_l}
    else:
        global usrs, gone
        usrs = usrs_l
        gone = gone_l
Exemple #11
0
def load_texts_used():
    log.D('+ load data_used from DB')
    conn = None
    com.d2u.data_used = []
    try:
        conn = psycopg2.connect(C.DATABASE_URL, sslmode='require')
        cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        cur.execute("SELECT * FROM data_used ORDER BY id")
        rows = cur.fetchall()
        for row in rows:
            com.d2u.data_used.append(row['value'])
    except psycopg2.DatabaseError as e:
        log.E('<ev.load_texts_used> DatabaseError %s' % e)
    else:
        log.I('+ data_used loaded successfully')
    finally:
        if conn:
            conn.close()
Exemple #12
0
def change_roles(callback,
                 member,
                 roles,
                 error_msg='',
                 delay=0,
                 by_id=False,
                 server_roles=None):
    """

    :param callback:
    :param member:
    :param roles:
    :param error_msg:
    :param delay: float|int in seconds
    :param by_id:
    :param server_roles:
    :return:
    """
    if not roles:
        return

    if not isinstance(roles, list):
        if is_iterable(roles):
            roles = list(roles)
        else:
            roles = [roles]

    if not error_msg:
        error_msg = callback

    if by_id:
        roles = get_roles(roles, server_roles)
    log.D('Try {t} to @{m.display_name} roles ({r}) // {msg}'.format(
        m=member,
        t=callback.__name__,
        r=', '.join([r.name for r in roles]),
        msg=error_msg))
    later_coro(delay, callback(member, roles, error_msg))
Exemple #13
0
async def on_member_update_u(before: C.Types.Member, after: C.Types.Member):
    # it's triggers on changing status, game playing, avatar, nickname or roles
    #
    if after.id == C.users['bot']:
        return

    smth_happend = False
    a_n = other.uname(after) + f' [{after.id}]'

    if before.display_name != after.display_name or before.name != after.name:
        smth_happend = True
        b_n = other.uname(before)
        log.pr_news(f'<on_member_update> {b_n} change nickname to {a_n}.')

    if before.game != after.game:
        smth_happend = True
        if before.game and after.game:
            log.D(
                f'<on_member_update> {a_n} go play from {before.game.name} to {after.game.name}.'
            )
        elif before.game:
            log.D(f'<on_member_update> {a_n} stop play {before.game.name}.')
        elif after.game:
            log.D(f'<on_member_update> {a_n} start play {after.game.name}.')
        else:
            log.D(
                f'<on_member_update> {{???}} {a_n} - game change, but there are no games...'
            )

        if after.id == C.users['Natali']:
            if before.game and C.prm_server.me.game.name == before.game.name:
                await other.set_game('')
            if after.game and not C.prm_server.me.game:
                await other.set_game(after.game.name)

        user_g = user_games.pop(after.id, {'name': '', 'h': 0})
        # degradation
        if False and other.rand() < 0.5 and (
                before.game and before.game.name
                and after.id not in ram.ignore_users and people.was_writing(
                    after.id, 48) and user_g['h'] >= TMR_IN_H):
            phr = com.get_t('game',
                            user=f'<@{after.id}>',
                            game=f"«{user_g['name']}»")
            com.write_msg(C.main_ch, phr)

        if after.game and after.game.name:
            user_games[after.id] = {'name': after.game.name, 'h': 0}

    if before.avatar_url != after.avatar_url:
        smth_happend = True
        urls = []
        for url in (before.avatar_url, after.avatar_url):
            urls.append(' ?'.join(url.split('?', maxsplit=1)))
        b_url, a_url = urls

        if before.avatar_url and after.avatar_url:
            await log.pr_avs(
                f'<on_member_update> {a_n} change avatar from \n{a_url} \nto\n{b_url}'
            )
        elif before.avatar_url:
            await log.pr_avs(
                f'<on_member_update> {a_n} delete avatar: \n{b_url}')
        elif after.avatar_url:
            await log.pr_avs(f'<on_member_update> {a_n} set avatar: \n{a_url}')
        else:
            log.I(
                f'<on_member_update> {{???}} {a_n} - avatar change, but there are no avatar_urls...'
            )

        # small degradation
        if (other.rand() < 0.01 and after.avatar_url
                and after.id not in ram.ignore_users
                and people.was_writing(after.id, 48)):
            phr = com.get_t('new_avatar', user=f'<@{after.id}>')
            com.write_msg(C.main_ch, phr)

    if before.roles != after.roles:
        smth_happend = True
        old_roles = [('@&' + r.name) for r in before.roles
                     if r not in after.roles]
        new_roles = [('@&' + r.name) for r in after.roles
                     if r not in before.roles]
        if old_roles:
            log.pr_news(
                f'<on_member_update> {a_n} lost role(s): {", ".join(old_roles)}.'
            )
        if new_roles:
            log.pr_news(
                f'<on_member_update> {a_n} get role(s): {", ".join(new_roles)}.'
            )
            new_role_ids = {r.id for r in after.roles if r not in before.roles}
            new_clan_roles = C.clan_ids.intersection(new_role_ids)
            has_clan_before = other.has_roles(before, C.clan_ids)
            if after.id not in not_embrace and new_clan_roles and not has_clan_before:
                clan_id = other.choice(new_clan_roles)
                clan_name = C.role_by_id[clan_id]
                log.pr_news(
                    f'<on_member_update> {a_n} get new clan role "{clan_name}" => call do_embrace.'
                )
                manager.just_embrace_say(after, clan_name=clan_name)
                # if sir_id:
                #     if clan_id in C.clan_channels:
                #         clan_ch = C.clan_channels[clan_id]
                #         phr = com.get_t(all_keys=('clan_welcome', clan_ch), user=f'<@{after.id}>', sir=f'<@{sir_id}>')
                #         com.write_msg(clan_ch, phr)

            elif has_clan_before and C.roles['Pander'] in new_clan_roles:
                log.jI(
                    f'<on_member_update> {a_n} go to Pander => delete other clan roles if it\'s exist.'
                )
                del_clans_id = C.clan_ids.difference({C.roles['Pander']})
                rem_roles = {r for r in after.roles if r.id in del_clans_id}
                if rem_roles:
                    other.rem_roles(after, rem_roles, 'on_member_update_u[1]')
                    str_rem_r = f"<@&{'>, <@&'.join(r.id for r in rem_roles)}>"
                    phr = com.get_t('to_Pander',
                                    user=f'<@{after.id}>',
                                    old_clans=str_rem_r,
                                    pander=f"<@&{C.roles['Pander']}>")
                    com.write_msg(C.main_ch, phr)
            elif C.roles['Mortal'] in new_role_ids:
                if has_clan_before:
                    # go to food
                    rem_roles = {
                        r
                        for r in after.roles
                        if r.id not in C.mortal_can_have_roles
                    }
                    other.rem_roles(after, rem_roles, 'go to Mortal(food)')
                    log.pr_news(f'<on_member_update> {a_n} go to food')
                else:
                    # new user
                    await C.client.send_message(C.main_ch,
                                                com.welcome_msg(before.id))
                    log.pr_news(f'<on_member_update> {a_n} welcome')

            if C.roles['Sabbat'] in new_role_ids:
                clan_ch = C.clan_channels[C.roles['Sabbat']]
                phr = com.get_t(all_keys=('clan_welcome', clan_ch),
                                user=f'<@{after.id}>')
                com.write_msg(clan_ch, phr)

    if before.status != after.status or not smth_happend:
        people.online_change(after.id,
                             after.status,
                             force=before.status == after.status)
        # small degradation
        _check_status_change(after)

    if (smth_happend
            or people.is_online(after.id)) and before.roles == after.roles:
        on_user_life_signs(after.id)
Exemple #14
0
def upd():
    t = load(res=True)
    log.D('- start upd people tables')
    log_upd = {
        'change_usrs': {
            'add': [],
            'upd': [],
            'del': []
        },
        'change_gone': {
            'add': [],
            'upd': [],
            'del': []
        }
    }
    change_usrs = {'add': [], 'upd': [], 'del': []}
    for uid in list(usrs.keys()):
        usr = usrs[uid]
        if usr.status == 'add' or usr.status == 'upd':
            if uid in t['usrs']:
                change_usrs['upd'].append(usr.row_upd())
                log_upd['change_usrs']['upd'].append(usr.name)
            else:
                change_usrs['add'].append(usr.row_add())
                log_upd['change_usrs']['add'].append(usr.name)
            usr.status = ''
        elif usr.status == 'del':
            if uid in t['usrs']:
                change_usrs['del'].append([uid])
                log_upd['change_usrs']['del'].append(usr.name)
            usrs.pop(uid)

    change_gone = {'add': [], 'upd': [], 'del': []}
    for uid in list(gone.keys()):
        gn = gone[uid]
        if gn.status == 'add' or gn.status == 'upd':
            if uid in t['gone']:
                change_gone['upd'].append(gn.row_upd())
                log_upd['change_gone']['upd'].append(gn.name)
            else:
                change_gone['add'].append(gn.row_add())
                log_upd['change_gone']['add'].append(gn.name)
            gn.status = ''
        elif gn.status == 'del':
            if uid in t['gone']:
                change_gone['del'].append([uid])
                log_upd['change_gone']['del'].append(gn.name)
            gone.pop(uid)

    if log.debug():
        if C.is_test:
            log.D("- it's Test mode, print results and return")
        log_upd = {'change_usrs': change_usrs, 'change_gone': change_gone}
        log.jD(
            'subjects were updated:\n', '\n'.join([
                cat + ':\n\t' + '\n'.join([
                    tp + '[{0}]:\n\t\t'.format(len(u_s)) +
                    ',\n\t\t'.join(str(u) for u in u_s)
                    for tp, u_s in ls.items() if u_s
                ]) for cat, ls in log_upd.items() if ls
            ]))
        # log.p('--------------------------------------------------------')
        if C.is_test:
            return

    conn = None
    log.D('- update people tables')
    try:
        ch_usrs_par = ', '.join(Usr.upd_props)
        ch_usrs_par_s = ', '.join(('%s', ) * len(Usr.upd_props))
        ch_gone_par = ', '.join(Gn.upd_props)
        ch_gone_par_s = ', '.join(('%s', ) * len(Gn.upd_props))
        conn = psycopg2.connect(C.DATABASE_URL, sslmode='require')
        cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        if change_usrs['add']:
            query = f'''INSERT INTO members (id, {ch_usrs_par})
                                            VALUES (%s, {ch_usrs_par_s})'''
            cur.executemany(query, change_usrs['add'])
            conn.commit()

        if change_gone['add']:
            query = f'''INSERT INTO users_gone (id, {ch_gone_par}) 
                                                        VALUES (%s, {ch_gone_par_s})'''
            cur.executemany(query, change_gone['add'])
            conn.commit()

        if change_usrs['upd']:
            query = f'''UPDATE members SET ({ch_usrs_par}) = 
                                                          ({ch_usrs_par_s}) WHERE id = %s'''
            cur.executemany(query, change_usrs['upd'])
            conn.commit()

        if change_gone['upd']:
            query = f'''UPDATE users_gone SET ({ch_gone_par}) = ({ch_gone_par_s}) WHERE id = %s'''
            cur.executemany(query, change_gone['upd'])
            conn.commit()

        if change_usrs['del']:
            query = '''DELETE FROM members WHERE id = %s'''
            cur.executemany(query, change_usrs['del'])
            conn.commit()

        if change_gone['del']:
            query = '''DELETE FROM users_gone WHERE id = %s'''
            cur.executemany(query, change_gone['del'])
            conn.commit()

    except psycopg2.DatabaseError as e:
        log.E('DatabaseError %s' % e)
        sys.exit(1)
    else:
        log.D('+ people tables updated successfully')
        log.jD(
            'subjects were updated:\n', '\n'.join([
                cat + ':\n\t' + '\n'.join([
                    tp + '[{0}]:\n\t\t'.format(len(u_s)) +
                    ',\n\t\t'.join(str(u) for u in u_s)
                    for tp, u_s in ls.items() if u_s
                ]) for cat, ls in log_upd.items() if ls
            ]))
    finally:
        if conn:
            conn.close()