from rest_framework.views import APIView
from rest_framework.response import Response
import math

class PostProcView(APIView):

    def largest_remainder(self, options, q, points, zero_votes):
        out = []
        e = []
        r = []

        if not zero_votes:
            if len(options) == 0:
                raise(Exception('Bad request: There are no options'))

            for opt in options:
                if q == 0:
                    ei = 0
                else:
                    ei = math.floor(opt['votes'] / q)

                e.append(ei)
                r.append(opt['votes'] - q * ei)

            k = points - sum(e)

            for x in range(k):
                grtst_rest_index = r.index(max(r))
                e[grtst_rest_index] = e[grtst_rest_index] + 1
                r[grtst_rest_index] = -1

        cont = 0
        for opt in options:
            out.append({
                **opt,
                'postproc': 0 if zero_votes else e[cont],
            })
            cont += 1

        out.sort(key=lambda x: (-x['postproc'], -x['votes']))
        return out

    def identity(self, options):
        out = []

        for opt in options:
            out.append({
                **opt,
                'postproc': opt['votes'],
            })

        out.sort(key=lambda x: -x['postproc'])
        return out

    def borda(self, options):
        out = []

        if len(options) == 0:
            raise(Exception('Bad request: There no options'))

        for opt in options:
            votes = 0
            options_number = len(options)
            for i in range(0, options_number):
                votes += opt['votes'][i] * (options_number - i)
            out.append({
                **opt,
                'postproc': votes,
            })

        out.sort(key=lambda x: -x['postproc'])
        return out

    def equality(self, options):
        out = []
        n_women = 0
        n_men = 0

        if len(options) == 0:
            raise(Exception('Bad request: There are no options'))

        for opt in options:
            n_women += opt['votes_fem']
            n_men += opt['votes_masc']

        if n_men == 0 or n_women == 0:
            for opt in options:
                votes = opt['votes_fem'] + opt['votes_masc']
                out.append({
                    **opt,
                    'postproc': votes,
                })
        else:
            for opt in options:
                if n_women > n_men:
                    votes = opt['votes_masc'] + opt['votes_fem'] * (n_men / n_women)
                else:
                    votes = opt['votes_fem'] + opt['votes_masc'] * (n_women / n_men)

                out.append({
                    **opt,
                    'postproc': round(votes),
                })

        out.sort(key=lambda x: -x['postproc'])

        return out

    def droop(self, options):
        total_votes = 0
        points = None

        for opt in options:
            if points is None: points = opt['points']
            total_votes += opt['votes']

        q = round(1 + total_votes / (points + 1))

        return self.largest_remainder(options, q, points, total_votes == 0)

    def proportional_representation(self, options, type):
        out = []
        votes = []
        points_for_opt = []
        multiplier = 2 if type == 'SAINTE_LAGUE' else 1
        points = options[0]['points']
        zero_votes = True

        for i in range(0, len(options)):
            votes.append(options[i]['votes'])
            points_for_opt.append(0)
            if zero_votes is True and options[i]['votes'] != 0:
                zero_votes = False

        if zero_votes is False:
            for i in range(0, points):
                max_index = votes.index(max(votes))
                points_for_opt[max_index] += 1
                votes[max_index] = options[max_index]['votes'] / (multiplier * points_for_opt[max_index] + 1)

        for i in range(0, len(options)):
            out.append({
                **options[i],
                'postproc': points_for_opt[i],
            })

        out.sort(key=lambda x: (-x['postproc'], -x['votes']))
        return out

    def imperiali(self, options):
        total_votes = 0
        points = None

        for opt in options:
            if points is None: points = opt['points']
            total_votes += opt['votes']

        q = round(total_votes / (points + 2))

        return self.largest_remainder(options, q, points, total_votes == 0)

    def hare(self, options):
        total_votes = 0
        points = None

        for opt in options:
            if points is None: points = opt['points']
            total_votes += opt['votes']

        if points == 0:
            q = 0
        else:
            q = round(total_votes / points)

        return self.largest_remainder(options, q, points, total_votes == 0)

      ##   return self.largest_remainder(options, q, points)

    def post(self, request):
        out = []
        questions = request.data

        for q in questions:
            result = None
            t = q['type']
            opts = q['options']

            if t == 'IDENTITY':
                result = self.identity(opts)
            if t == 'BORDA':
                result = self.borda(opts)
            if t == 'EQUALITY':
                result = self.equality(opts)
            if t == 'SAINTE_LAGUE' or t == 'HONDT':
                result = self.proportional_representation(opts, t)
            if t == 'DROOP':
                result = self.droop(opts)
            if t == 'IMPERIALI':
                result = self.imperiali(opts)
            if t == 'HARE':
                result = self.hare(opts)

            out.append({'type': t, 'options': result})

        return Response(out)


# BAP 2019
# Author: Axel Claeijs
# This script uses the trained network to make predictions

#-----------------------------------------------------------
# IMPORTS
#-----------------------------------------------------------
import sys
import cv2
import math
import pptk

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf

from scipy.ndimage.interpolation import rotate
from proto import pointcloud_pb2

#-----------------------------------------------------------
# VARIABLES
#-----------------------------------------------------------
VERSION = 7
MODEL_PATH = 'results/v' + str(VERSION) + '/trained_model' + str(VERSION) + '.h5'
ANGLE = np.random.randint(0,35)
EXTEND_DATA = 0     # Wheter or not to extend dataset with rotated variants

#-----------------------------------------------------------
# EXTEND DATASET
#-----------------------------------------------------------
def rotateLabels(labels, degree):
    temp_label = labels.reshape((40, 40))
    temp_label = rotate(temp_label, -degree, mode='constant', reshape=False).reshape(1600)
    return np.array(temp_label)

def rotateData(data, degree):
    radian = math.radians(degree)

    rotMatrix = np.array([[np.cos(radian), -np.sin(radian), 0],
                          [np.sin(radian), np.cos(radian), 0],
                          [0, 0, 1]])
    new_pc = []
    for i in range(len(data)):
        new_pc.append(np.dot(data[i], rotMatrix))

    return np.array(new_pc)

#-----------------------------------------------------------
# CALC FP
#-----------------------------------------------------------
def false_positive(image_p, image_r):
    count = 0
    image_p_vec = image_p.reshape(1600)
    image_r_vec = image_r.reshape(1600)

    for i in range(1600):

        # pixel is predicted as object while it is free space
        if ((image_p_vec[i] >= 0.5) and (image_r_vec[i] < 0.5)):
            count += 1

    # false positives / number of negatives
    return count/len(sum(np.where(image_r_vec < 0.5)))

#-----------------------------------------------------------
# CALC fn
#-----------------------------------------------------------
def false_negative(image_p, image_r):
    count = 0
    image_p_vec = image_p.reshape(1600)
    image_r_vec = image_r.reshape(1600)

    for i in range(1600):

        # pixel is predicted as free space while it is an object
        if ((image_p_vec[i] < 0.5) and (image_r_vec[i] >= 0.5)):
            count += 1

    # false negatives / number of positives
    if count == 0:
        return 0
    else:
        return count /len(sum(np.where(image_r_vec >= 0.5)))

#-----------------------------------------------------------
# FETCHING DATA
#-----------------------------------------------------------

if len(sys.argv) != 2:
    print("Usage:", sys.argv[0], "COLLECTION_FILE")
    sys.exit(-1)

collection = pointcloud_pb2.PairCollection()

# Open input and output files
inputFile = open(sys.argv[1], "rb")

# Read the existing collection.
collection.ParseFromString(inputFile.read())
inputFile.close()

data = []
label = []
label_new = []

# Append each PC and CM to the train and label set
valid = 0
for pair in collection.pair:

    pcPoints = []
    for pt in pair.pointcloud.points:
        pcPoints.append([pt.x, pt.y, pt.z])
        # np.append(pcPoints, [pt.x, pt.y, pt.i])

    # Only add scans of 300 points
    if len(pcPoints) == 300:
        data.append(np.array(pcPoints))
        label.append(pair.costmap.data)

# Train set with shape: (#pc, 300, 2)
data = np.array(data)

# Label set with shape: (#cm, 14400)
label = np.array(label)

# Normalize the labels
label = label/100

for i in range(len(label)):
    temp = label[i].reshape((120, 120))
    label_new.append(cv2.resize(temp, dsize=(40, 40), interpolation=cv2.INTER_CUBIC).reshape(1600))

# Label set with shape: (#cm, 1600)
label = np.array(label_new)

#-----------------------------------------------------------
# MAIN
#-----------------------------------------------------------
model = tf.keras.models.load_model(MODEL_PATH)

SAMPLE = np.random.randint(0, len(data))
data_sample = data[SAMPLE]
label_sample = label[SAMPLE]

if EXTEND_DATA:
    data_sample = rotateData(data_sample, ANGLE)
    label_sample = rotateLabels(label_sample, ANGLE)

#print((np.array([data_sample,])).shape)

#predict the result
result = model.predict(np.array([data_sample,]))

image_p = result.reshape((40, 40))
plt.figure()
# plt.subplot(2, 1, 1)
plt.imshow(image_p)
plt.colorbar(label='Intensity')
plt.title('Predicted Costmap - ' + str(SAMPLE))
plt.xlabel('X')
plt.ylabel('Y')
plt.show()

image_r = label_sample.reshape(40, 40)
plt.figure()
# plt.subplot(2, 1, 2)
plt.imshow(image_r)
plt.colorbar(label='Intensity')
plt.title('Real Costmap - ' + str(SAMPLE))
plt.xlabel('X')
plt.ylabel('Y')
plt.show()

plt.tight_layout()

# temp = 'predictCostmap_sample' + str(SAMPLE) + '.png'
# plt.savefig(temp)
plt.show()

v = pptk.viewer(data_sample.tolist())
v.set(floor_level=0)
v.set(point_size=0.05)
v.set(r=30)
v.set(theta=180)
v.set(phi=270)
v.set(bg_color=(0, 0, 0, 1))

# temp = 'predictPointcloud_sample' + str(SAMPLE) + '.png'
# v.capture(temp)


import sqlite3
from aiocryptopay import AioCryptoPay, Networks
from config import cryptobot_test_net, cryptobot_main_net
from database.db_keys import user_table, k_user_id, k_locate, k_login, k_key, k_addres

cp = AioCryptoPay(token=cryptobot_main_net, network=Networks.MAIN_NET)

sql_create_users_table = f""" CREATE TABLE IF NOT EXISTS {user_table} (
                                        id integer PRIMARY KEY,
                                        {k_user_id} text NOT NULL,
                                        {k_login} text,
                                        {k_locate} text,
                                        {k_key} text,
                                        {k_addres} text,
                                        join_date datetime
                                    ); """

sql_create_record_table = f""" CREATE TABLE IF NOT EXISTS records (
                                        id integer PRIMARY KEY,
                                        {k_user_id} text NOT NULL,
                                        amount text,
                                        operation real
                                    ); """

sql_create_sequence_table = """ CREATE TABLE IF NOT EXISTS sqlite_sequence (
                                        name text NOT NULL,
                                        seq text
                                    ); """
sql_create_trans_table = f""" CREATE TABLE IF NOT EXISTS transactions (
                                        id integer PRIMARY KEY,
                                        {k_user_id} text NOT NULL,
                                        currency text NOT NULL,
                                        amount real
                                    ); """

class db:
    def __init__(self, db_file):
        self.conn = sqlite3.connect(db_file)
        self.cursor = self.conn.cursor()
        try:
            self.cursor.execute(sql_create_trans_table)
            # self.cursor.execute(sql_create_sequence_table)
            self.cursor.execute(sql_create_record_table)
            self.cursor.execute(sql_create_users_table)
        except Exception as e:
            print(e)

    def row_exist(self, table, id):
        #Проверяем, есть ли юзер в базе
        result = self.cursor.execute(f"SELECT `id` FROM `{table}` WHERE `{k_user_id}` = ?", (id,))
        return bool(len(result.fetchall()))

    def user_exists(self, user_id):
        #Проверяем, есть ли юзер в базе
        result = self.cursor.execute(f"SELECT `id` FROM `users` WHERE `{k_user_id}` = ?", (user_id,))
        return bool(len(result.fetchall()))

    def cell_exist(self,table,f_id,coll):
        result = self.cursor.execute(f"SELECT `{coll}` FROM `{table}` WHERE `{k_user_id}` = ?", (f_id,))
        f_res = result.fetchone()[0]
        return bool(f_res)

    def get_cell(self,table,coll,id):
        SQL = f"SELECT `{coll}` FROM `{table}` WHERE `{k_user_id}` = {id}"
        result = self.cursor.execute(SQL)
        return result.fetchone()[0]
    def get_row(self,table, id):
        #Достаем id юзера в базе по его user_id
        result = self.cursor.execute(f"SELECT `id` FROM `{table}` WHERE `{k_user_id}` = `{id}`",)
        return result.fetchone()[0]

    def get_user_id(self, user_id):
        #Достаем id юзера в базе по его user_id
        result = self.cursor.execute(f"SELECT `id` FROM `users` WHERE `{k_user_id}` = ?", (user_id,))
        return result.fetchone()[0]

    def get_used_locate(self, user_id):
        result = self.cursor.execute(f"SELECT `{k_locate}` FROM `{user_table}` WHERE `{k_user_id}` = ?", (user_id,))
        return result.fetchone()[0]

    def add_row(self,table,data):
        f_sql = f'INSERT INTO "{table}" ('
        f_values = ''
        for q_key in data.keys():
            f_sql += f'"{q_key}", '
            f_values += f'"{data[q_key]}",'
        f_sql = f_sql.removesuffix(', ')
        f_values = f_values.removesuffix(',')
        f_sql += f") VALUES ({f_values})"
        self.cursor.execute(f_sql)
        return self.conn.commit()

    def add_cell(self,table,f_id,coll,data):
        # data = '0x' + data
        data = data.removeprefix("0x")
        self.cursor.execute(f"UPDATE `{table}` SET `{coll}` = '%s' WHERE `{k_user_id}` = {f_id}" % data)
        return self.conn.commit()

    def add_user(self, user_id,f_key):
        #Добавляем юзера в базу
        self.cursor.execute(f"INSERT INTO `users` (`{k_user_id}`, `{k_locate}`) VALUES (?,?)", (user_id,f_key))
        return self.conn.commit()

    # def add_user(self, user_id):
    #     #Добавляем юзера в базу
    #     self.cursor.execute("INSERT INTO `users` (`user_id`) VALUES (?)", (user_id,))
    #     return self.conn.commit()

    def add_records(self, user_id, operation, amount):
        #Создаем записи о депозитах и выводах
        self.cursor.execute(f"INSERT INTO 'records'('{k_user_id}', 'operation', 'amount') VALUES (?, ?, ?)", (self.get_user_id(user_id),
                                                                                operation,
                                                                                amount))
        return self.conn.commit()

    def get_balance(self, user_id):
        #Счетаем баланс пользователя
        c = self.cursor.execute(f'SELECT COALESCE(SUM(CASE WHEN operation = "+" THEN amount ELSE -amount END), 0) AS balance FROM records WHERE {k_user_id} = ?', (self.get_user_id(user_id),))
        return c.fetchall()

    # def add_record(self, user_id, currency, amount):
    #     #Создаем запись о депозите
    #     self.cursor.execute("INSERT INTO `transactions` (`users_id`,'currency', 'amount') VALUES (?, ?, ?)", (self.get_user_id(user_id),
    #                                                                                currency,
    #                                                                                amount))
    #     return self.conn.commit()
    #
    # async def get_balance(self, user_id):
    #     #Считаем баланс пользователя
    #     c = self.cursor.execute("SELECT currency, SUM(amount) FROM transactions WHERE users_id=? GROUP BY currency", (self.get_user_id(user_id),))
    #     run_equivalent = 0.0
    #     rub_equivalent = 0.0
    #     rates = await cp.get_exchange_rates()
    #     results = c.fetchall()
    #     arr ='\n'
    #     for row in results:
    #         currency, balance = row
    #         match currency:
    #             case ("USDT"):
    #                 run_equivalent += balance * rates[0].rate
    #                 rub_equivalent = balance * rates[0].rate
    #             case ("TON"):
    #                 run_equivalent += balance * rates[18].rate
    #                 rub_equivalent = balance * rates[18].rate
    #             case ("ETH"):
    #                 run_equivalent += balance * rates[54].rate
    #                 rub_equivalent = balance * rates[54].rate
    #             case ("BNB"):
    #                 run_equivalent += balance * rates[72].rate
    #                 rub_equivalent = balance * rates[72].rate
    #             case ("BUSD"):
    #                 run_equivalent += balance * rates[90].rate
    #                 rub_equivalent = balance * rates[90].rate
    #             case ("USDC"):
    #                 run_equivalent += balance * rates[108].rate
    #                 rub_equivalent = balance * rates[108].rate
    #
    #         arr += f"{currency}: {balance}    <=>   {rub_equivalent} руб\n"
    #     arr += f"\n Ваш баланс : {run_equivalent} руб"
    #     return arr
    #
    # async def rub_balance(self, user_id):
    #     #Считаем баланс пользователя в рублях
    #     c = self.cursor.execute("SELECT currency, SUM(amount) FROM transactions WHERE users_id=? GROUP BY currency",
    #                             (self.get_user_id(user_id),))
    #     balance = 0.0
    #     rates = await cp.get_exchange_rates()
    #     results = c.fetchall()
    #     for row in results:
    #         currency, b = row
    #         match currency:
    #             case ("USDT"):
    #                 balance += b * rates[0].rate
    #             case ("TON"):
    #                 balance += b * rates[18].rate
    #             case ("ETH"):
    #                 balance += b * rates[54].rate
    #             case ("BNB"):
    #                 balance += b * rates[72].rate
    #             case ("BUSD"):
    #                 balance += b * rates[90].rate
    #             case ("USDC"):
    #                 balance += b * rates[108].rate
    #     return balance


# -*- coding: utf-8 -*-

import subprocess
import os
import sys
import socket
import logging
import dns.resolver #pip install dnspython

dominio = raw_input(str('Digite o nome do seu dominio: '))

# Path's
amavis_novalistadeverificacao = '/tmp/amavis_novalistadeverificacao'
amavis_novalistadeverificacaoip = '/tmp/amavis_novalistadeverificacaoip'

# Zimbra Path's
if os.path.exists('/opt/zimbra/conf/postfix_blacklist'):
    postfix_blacklistfile = '/opt/zimbra/conf/postfix_blacklist'
else:
    subprocess.call(['touch', '/opt/zimbra/conf/postfix_blacklist'], shell=True)
# Postmap
if os.path.exists('/opt/zimbra/postfix/sbin/postmap'):
    postmap = '/opt/zimbra/postfix/sbin/postmap'
elif os.path.exists('/opt/zimbra/common/sbin/postmap'):
    postmap = '/opt/zimbra/common/sbin/postmap'
else:
    logging.error('postmap nao encontrado...')
    print('caminho para o postmap nao encontrado, o Zimbra esta instalado?')
    sys.exit(1)
# Zmprov
if os.path.exists('/opt/zimbra/bin/zmprov'):
    zmprov = '/opt/zimbra/bin/zmprov'
else:
    logging.error('zmprov nao encontrado...')
    print('caminho para o zmprov nao encontrado, o Zimbra esta instalado?')
    sys.exit(1)

# Commands
cmd_awk2 = "'{print $2}'"
cmd_apagalinhasembranco = "'/^$/d'"

# Logs
logging.basicConfig(filename='/opt/pyAntispam/log/pyaddblacklist.log', format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)

# 1
def listadeverificacao_tratada():
    try:

        if os.path.exists(amavis_novalistadeverificacao):
            amavis_listadeverificacao = open(amavis_novalistadeverificacao, 'r').read().split('\n')
            amavis_novalista = []
            amavis_listadeverificacao = sorted(amavis_listadeverificacao)
            for item in amavis_listadeverificacao:
                try:
                    for dominio in item.splitlines():
                        k, v = dominio.split("@", 2)
                        amavis_novalista.append(v)
                        logging.info('adicionando item a lista de verificacao: %s' % (v))
                except ValueError as e:
                    logging.error(e)
                    amavis_novalista.append(dominio)
                    logging.info('adicionando item a lista de verificacao: %s' % (dominio))

        lista_unica = []

        for item in amavis_novalista:
            if item not in lista_unica:
                logging.info('removendo itens repetidos na lista: %s' % (item))
                lista_unica.append(item)

        lista_unica = sorted(lista_unica)

    except Exception as e:
        print('definicao listadeverificacao_tratada erro: %s' % (e))
        logging.error('definicao listadeverificacao_tratada erro: %s' % (e))

    return lista_unica
# 2
def amavis_listatual():
    amavis_coletalistatual = 'zmprov gd %s amavisBlacklistSender | grep -v %s | awk %s | sed %s > /tmp/amavis_%s_blacklist' % (dominio, dominio, cmd_awk2, cmd_apagalinhasembranco, dominio)
    subprocess.call(amavis_coletalistatual, shell=True)
    try:
        if os.path.exists('/tmp/amavis_%s_blacklist' % (dominio)):
            amavis_listatual_dominios = ('/tmp/amavis_%s_blacklist' % (dominio))
            amavis_listatual_bruta = open(amavis_listatual_dominios, 'r').read().split('\n')
            amavis_listatual_bruta = sorted(amavis_listatual_bruta)

            amavis_listatual = []

            for item in amavis_listatual_bruta:
                if item != "":
                    amavis_listatual.append(item)
                    logging.info('adicionando item a lista atual: %s' % (item))
        else:
            print('Lista atual não encontrada. Chame o suporte.')
            logging.error('Lista atual não encontrada. Chame o suporte.')
            sys.exit(1)

        amavis_listatual = sorted(amavis_listatual)

        return amavis_listatual

    except Exception as e:
        print('definicao amavis_listatual erro: %s' % (e))
        logging.error('definicao amavis_listatual erro: %s' % (e))
# 3
def comparando_listas(atual, checagem):
    listapara_adesao = []
    try:
        for item in checagem:
            if item not in atual:
                logging.info('adicionando item para lista de adesao: %s' % (item))
                listapara_adesao.append(item)
    except Exception as e:
        print('definicao comparando_listas erro: %s' % (e))
        logging.error('definicao comparando_lista erro: %s' % (e))

    listapara_adesao = sorted(listapara_adesao)

    return listapara_adesao
# 4
def lista_ips(data):
    try:
        lista_ips = []
        lista_mx = []
        lista_unica = []
        for mxs in data:
            for mx in dns.resolver.query(mxs, 'MX'):
                mx = mx.to_text()
                try:
                    for nome_mx in mx.splitlines():
                        k, v = nome_mx.split(" ", 2)
                        lista_mx.append(v)
                        logging.info('MX coletado: %s' % (v))
                except ValueError as e:
                    logging.error(e)

            for ips in lista_mx:
                try:
                    if socket.gethostbyname(ips):
                        ip = socket.gethostbyname(ips)
                        lista_ips.append(ip)
                except Exception as e:
                    logging.warning('nao foi possivel resolver o ip do dominio: %s' % (ips))
                    print('nao foi possivel resolver o ip do dominio: %s' % (ips))
    except Exception as e:
        print('definicao lista_ips erro: %s' % (e))
        logging.error('definicao lista_ips erro: %s' % (e))

    for item in lista_ips:
        if item not in lista_unica:
            logging.info('removendo itens repetidos na lista: %s' % (item))
            lista_unica.append(item)

    lista_ip = sorted(lista_unica)

    return lista_ip
# 5
def postfix_blacklist(data):
# pegar a lista atual
    arquivo_blacklist = 'cat %s > %s' % (postfix_blacklistfile, amavis_novalistadeverificacaoip)
    subprocess.call(arquivo_blacklist, shell=True)
    blacklist_atual = open(amavis_novalistadeverificacaoip, 'r').read().split('\n')
    blacklist_atual = sorted(blacklist_atual)
    del blacklist_atual [0]

    lista_unica = []
    lista_ipatual = []
    lista_ipadesao = []
# O arquivo é alimentado IP REJECT por linha. Exemplo 1.1.1.1 REJECT
    try: # Separa IP REJECT
        for ip in blacklist_atual:
            if ip != '':
                for ip_atual in ip.splitlines():
                    k, v = ip_atual.split(" ", 1)
                    lista_ipatual.append(k)

        for item in lista_ipatual:
            if item not in lista_unica:
                logging.info('removendo itens repetidos caso existam na lista: %s' % (item))
                lista_unica.append(item)

        for ip_novo in data:
            if ip_novo not in lista_unica:
                lista_ipadesao.append(ip_novo)
                logging.info('adicionando ip: %s a lista de adesao.' % (ip_novo))

        if not len(lista_ipadesao) == 0:
            for ip_adesao in lista_ipadesao:
                print('incluindo ip: %s' % (ip_adesao))
                cmd_shell = "echo '%s REJECT' >> %s" % (ip_adesao, postfix_blacklistfile)
                subprocess.call(cmd_shell, shell=True)
                logging.info('incluindo ip: %s' % (ip_adesao))

            cmd_postmap = '%s %s' % (postmap, postfix_blacklistfile)
            subprocess.call(cmd_postmap, shell=True)

        else:
            logging.warning('nao existem novas entradas ips')
            print('nao existem novas entradas ips.')

    except Exception as e:
        print('definicao postfix_blacklist erro: %s' % (e))
        logging.error('definicao postfix_blacklist erro: %s' % (e))
# 6
def amavis_blacklistsender(data):
    try:
        if not len(data) == 0:
            for dominio_adesao in data:
                cmd_zmprov = '%s md %s +amavisBlacklistSender %s' % (zmprov, dominio, dominio_adesao)
                subprocess.call(cmd_zmprov, shell=True)
        else:
            logging.info('nao existem novas entradas dominio.')
            print('nao existem novas entradas dominio.')
    except Exception as e:
        print('definicao amavis_blacklistsender erro: %s' % (e))
        logging.error('definicao amavis_blacklistsender erro: %s' % (e))

lista_ips(comparando_listas(amavis_listatual(), listadeverificacao_tratada()))
postfix_blacklist(lista_ips(comparando_listas(amavis_listatual(), listadeverificacao_tratada())))
amavis_blacklistsender(comparando_listas(amavis_listatual(), listadeverificacao_tratada()))


import random
from PyQt6.QtWidgets import QPushButton, QApplication, QMainWindow, QWidget, QGridLayout, QLabel
from PyQt6.QtGui import QAction, QIcon
from PyQt6.QtMultimedia import QSoundEffect
from PyQt6.QtCore import QSize, Qt, QCoreApplication, QPoint, QPropertyAnimation, QUrl
from PyQt6 import QtCore

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setWindowTitle("Minesweeper by Arthur Dubovik")
        self.setWindowIcon(QIcon("./img/mine.png"))

        #Sounds
        self.sound_click = QSoundEffect()
        self.sound_click.setSource(QUrl.fromLocalFile("./sound/click.wav"))
        self.sound_click.setVolume(0.5)
        self.sound_mine_check = QSoundEffect()
        self.sound_mine_check.setSource(QUrl.fromLocalFile("./sound/mine_check.wav"))
        self.sound_mine_check.setVolume(0.25)
        self.sound_mine_press = QSoundEffect()
        self.sound_mine_press.setSource(QUrl.fromLocalFile("./sound/mine_press.wav"))
        self.sound_mine_press.setVolume(0.25)
        self.sound_win = QSoundEffect()
        self.sound_win.setSource(QUrl.fromLocalFile("./sound/sound_win.wav"))
        self.sound_win.setVolume(0.5)

        #Button icons
        self.img_banner = QIcon("./img/banner.png")
        self.img_mine = QIcon("./img/mine.png")
        self.img_false_mine = QIcon("./img/false_mine.png")
        self.img_explode = QIcon("./img/explode_mine.png")

        #New game button
        button_action = QAction("New game", self)
        button_action.triggered.connect(self.new_game)

        #Difficult buttons
        self.button_action2_1 = QAction("10", self)
        self.button_action2_1.setCheckable(True)
        self.button_action2_1.setChecked(True)
        self.button_action2_1.triggered.connect(self.change_diff)

        self.button_action2_2 = QAction("25", self)
        self.button_action2_2.setCheckable(True)
        self.button_action2_2.triggered.connect(self.change_diff)

        self.button_action2_3 = QAction("40", self)
        self.button_action2_3.setCheckable(True)
        self.button_action2_3.triggered.connect(self.change_diff)

        #Field size buttons
        self.button_action3_1 = QAction("12 x 12", self)
        self.button_action3_1.setCheckable(True)
        self.button_action3_1.setChecked(True)
        self.button_action3_1.triggered.connect(self.change_size)

        self.button_action3_2 = QAction("16 x 16", self)
        self.button_action3_2.setCheckable(True)
        self.button_action3_2.triggered.connect(self.change_size)

        self.button_action3_3 = QAction("20 x 20", self)
        self.button_action3_3.setCheckable(True)
        self.button_action3_3.triggered.connect(self.change_size)

        #Exit button
        button_action4 = QAction("Exit", self)
        button_action4.triggered.connect(QCoreApplication.instance().quit)

        #Creating menu bar
        menu = self.menuBar()

        file_menu = menu.addMenu("Menu")
        file_menu.addAction(button_action)
        #_______________________
        file_menu.addSeparator()
        file_submenu = file_menu.addMenu("Difficult")
        file_submenu.addAction(self.button_action2_1)
        file_submenu.addAction(self.button_action2_2)
        file_submenu.addAction(self.button_action2_3)

        file_submenu = file_menu.addMenu("Field size")
        file_submenu.addAction(self.button_action3_1)
        file_submenu.addAction(self.button_action3_2)
        file_submenu.addAction(self.button_action3_3)
        #_______________________
        file_menu.addSeparator()
        file_menu.addAction(button_action4)

    #Filling the playing field with buttons
    def init(self, height=12, width=12, mines=10):
        #List of buttons
        self.CELLS = []
        #Field size (number of buttons)
        self.HEIGHT = height
        self.WIDTH = width
        #Number of buttons with mines
        self.MINES = mines
        #Number of buttons marked with a flag
        self.CHECK_BUTTONS = 0
        #List of coordinates with cells of correctly marked mines
        self.CHECKED_MINES = []
        #Button size
        self.BUTTON_HEIGHT = self.BUTTON_WIDTH = 38
        #Padding between buttons
        self.BUTTON_INDENT = 1

        #Arrangement of elements in the window
        self.layout = QGridLayout()
        self.widget = QWidget()
        self.widget.setLayout(self.layout)
        self.setCentralWidget(self.widget)

        #Fixed size of the playing field for the number of buttons
        self.WIDTH_SIZE = self.HEIGHT * self.BUTTON_HEIGHT + (self.HEIGHT - 1) * self.BUTTON_INDENT
        self.HEIGHT_SIZE = self.WIDTH * self.BUTTON_WIDTH + (self.WIDTH - 1) * self.BUTTON_INDENT
        self.setFixedSize(QSize(self.WIDTH_SIZE+30, self.HEIGHT_SIZE+40))

        #Creating a grid of buttons
        for i in range(self.HEIGHT):
            for j in range(self.WIDTH):
                self.button = QPushButton("Button ", self)

                #Setting the size of buttons
                self.button.setFixedSize(QSize(self.BUTTON_HEIGHT, self.BUTTON_WIDTH))

                self.button.setCheckable(True)
                self.button.setText('')
                self.button.clicked.connect(self.open_cell)

                #Flag of the pressed button
                self.button.is_pressed = False
                #Flag of a marked mine
                self.button.mine_note = False
                #Status of the buttons after the victory
                self.button.win = False

                #Redefining the right mouse button
                self.button.installEventFilter(self)
                self.layout.addWidget(self.button, i, j)

                #Setting coordinates to buttons
                self.button.x = i
                self.button.y = j

                #Adding buttons to the list
                self.CELLS.append(self.button)

        #Victory label
        self.btn = QLabel(self)
        self.btn.setText('You win!')
        self.btn.resize(200, 60)
        self.btn.setStyleSheet('QLabel {font: bold 44px;}')
        self.btn.hide()

    #Victory
    def victory(self):
        self.btn.show()
        animation = QPropertyAnimation(self.btn, b'pos', self)
        animation.setKeyValueAt(0, QPoint(20, 30))
        animation.setKeyValueAt(0.65, QPoint(self.HEIGHT_SIZE - 200, self.WIDTH_SIZE - 100))
        animation.setKeyValueAt(1, QPoint(int((self.HEIGHT_SIZE - 200) / 2), int((self.WIDTH_SIZE - 100) / 2)))
        animation.setDuration(20000)
        animation.start()
        self.sound_win.play()

    #New game event
    def new_game(self):
        self.sound_win.stop()
        self.btn.hide()
        self.new = False

        window.init(self.HEIGHT, self.WIDTH, self.MINES)
        pole_game.pole = []
        pole_game.init(self.HEIGHT, self.WIDTH, self.MINES)

    #Changing the difficulty
    def change_diff(self):
        sender = self.sender()
        sender.setChecked(True)
        if sender.text() == "10":
            self.MINES = 10
            self.button_action2_2.setChecked(False)
            self.button_action2_3.setChecked(False)
            self.new_game()

        if sender.text() == "25":
            self.MINES = 25
            self.button_action2_1.setChecked(False)
            self.button_action2_3.setChecked(False)
            self.new_game()

        if sender.text() == "40":
            self.MINES = 40
            self.button_action2_1.setChecked(False)
            self.button_action2_2.setChecked(False)
            self.new_game()

    #Field size selection
    def change_size(self):
        sender = self.sender()
        sender.setChecked(True)
        if sender.text() == "12 x 12":
            self.HEIGHT = self.WIDTH = 12
            self.button_action3_2.setChecked(False)
            self.button_action3_3.setChecked(False)
            self.new_game()

        if sender.text() == "16 x 16":
            self.HEIGHT = self.WIDTH = 16
            self.button_action3_1.setChecked(False)
            self.button_action3_3.setChecked(False)
            self.new_game()

        if sender.text() == "20 x 20":
            self.HEIGHT = self.WIDTH = 20
            self.button_action3_1.setChecked(False)
            self.button_action3_2.setChecked(False)
            self.new_game()

    #Opening a field by click
    def open_cell(self):

        #The object of the pressed button
        sender = self.sender()
        sender.setChecked(True)
        if sender.mine_note != True and sender.is_pressed == False:
            self.sound_click.play()
            sender.is_pressed = True

            #Number of buttons pressed
            self.PRESS_BUTTONS = len(list(filter(self.check_true, [i.is_pressed for i in self.CELLS])))

            #Checking the victory conditions (if the last closed cell opens)
            self.win_check()

            #Clicking on a mine
            if pole_game.pole[sender.x][sender.y].mine == True:
                self.sound_mine_press.play()
                self.mine_press(sender)
            #Counting the mines around the pressed button
            elif pole_game.pole[sender.x][sender.y].around_mines > 0:
                    sender.setText(str(pole_game.pole[sender.x][sender.y].around_mines))

                    #Number custom colors
                    if sender.text() == '1':
                        sender.setStyleSheet('QPushButton {color: #3F51B5; font: bold 20px;}')
                    if sender.text() == '2':
                        sender.setStyleSheet('QPushButton {color: #8B0000; font: bold 20px;}')
                    if sender.text() == '3':
                        sender.setStyleSheet('QPushButton {color: #FF0000; font: bold 20px;}')
                    if sender.text() == '4':
                        sender.setStyleSheet('QPushButton {color: #03A9F4; font: bold 20px;}')
                    if sender.text() == '5':
                        sender.setStyleSheet('QPushButton {color: #006400; font: bold 20px;}')

            #If you clicked on an empty cell
            if pole_game.pole[sender.x][sender.y].around_mines == 0 and pole_game.pole[sender.x][sender.y].mine != True:
                self.rec_open(sender.x, sender.y)

    #Clicking on a mine
    def mine_press(self, sender):
        for i in self.CELLS:
            if [i.x, i.y] in pole_game.rij and i.mine_note == False:
                i.setCheckable(True)
                i.setChecked(True)
                i.setIcon(QIcon(self.img_mine))
                i.setIconSize(QSize(35,35))
            if i.isChecked() == False:
                i.setCheckable(False)
            if i.mine_note == True and [i.x, i.y] not in pole_game.rij:
                i.setIcon(QIcon(self.img_false_mine))
                i.setIconSize(QSize(38,38))
            i.is_pressed = True
        sender.setIcon(QIcon(self.img_explode))
        sender.setIconSize(QSize(35,35))

    #Opening empty cells around the selected empty one
    def rec_open(self, x, y):
        for i in self.CELLS:
            if i.is_pressed == False:
                if i.x == x and i.y == y + 1:
                    i.click()
                if i.x == x + 1 and i.y == y:
                    i.click()
                if i.x == x - 1 and i.y == y:
                    i.click()
                if i.x == x and i.y == y - 1:
                    i.click()
                if i.x == x + 1 and i.y == y + 1:
                    i.click()
                if i.x == x - 1 and i.y == y - 1:
                    i.click()
                if i.x == x - 1 and i.y == y + 1:
                    i.click()
                if i.x == x + 1 and i.y == y - 1:
                    i.click()

    @staticmethod
    def check_true(x):
        if x == True:
            return x

    #Right-click processing
    def eventFilter(self, obj, event):
        if event.type() == QtCore.QEvent.Type.MouseButtonPress:
            #if event.button() == Qt.MouseButton.LeftButton:
                #print(obj.objectName(), "Left click")

            if event.button() == Qt.MouseButton.RightButton:
                #print(obj.objectName(), "Right click")

                #Marking of mines on the field
                if obj.is_pressed == False and obj.win == False:
                    if obj.mine_note == False:
                        self.sound_mine_check.play()
                        obj.setIcon(QIcon(self.img_banner))
                        obj.setIconSize(QSize(34,34))
                        obj.mine_note = True
                        obj.setCheckable(False)

                        if pole_game.pole[obj.x][obj.y].mine == True:
                            if [obj.x, obj.y] not in self.CHECKED_MINES:
                                self.CHECKED_MINES.append([obj.x, obj.y])

                    else:
                        self.sound_mine_check.play()
                        obj.mine_note = False
                        obj.setIcon(QIcon())
                        obj.setCheckable(True)
                        if [obj.x, obj.y] in self.CHECKED_MINES:
                                self.CHECKED_MINES.remove([obj.x, obj.y])

                #Number of buttons marked with a flag
                self.check_buttons = len(list(filter(self.check_true, [i.mine_note for i in self.CELLS])))

                self.win_check()
                #elif event.button() == Qt.MouseButton.MiddleButton:
                    #print(obj.objectName(), "Middle click")
        return QtCore.QObject.event(obj, event)

    #Win check
    def win_check(self):
        if sorted(self.CHECKED_MINES) == sorted(pole_game.rij) and self.check_buttons == self.MINES:
            if self.PRESS_BUTTONS == len(self.CELLS) - self.MINES:
                self.CHECKED_MINES = []
                for i in self.CELLS:
                    i.win = True
                self.victory()

#Game cell
class Cell:
    def __init__(self, around_mines, mine):
        self.around_mines = around_mines
        self.mine = mine
        self.fl_open = False

#Game field
class GameField:
    def init(self, height=12, width=12, mines=10):
        #List size
        self.M = height
        self.N = width
        #Number of mines
        self.mines = mines

        #Filling the list of cells with zeros
        self.pole = [[(Cell(0, False)) for i in range(self.N)] for i in range(self.M)]

        #List with mines
        self.rij = []

        #Filling the field with mines
        mine_count = 0
        while mine_count < self.mines:
            r = [random.randrange(self.N), random.randrange(self.M)]
            if r not in self.rij:
                self.rij.append(r)
                self.pole[r[0]][r[1]].mine = True
                mine_count += 1

        #Counting the number of mines around each cell
        for i in range(self.M):
            for j in range(self.N):
                around_mines = 0
                for x in range(-1, 2):
                    for y in range(-1, 2):
                        if (i + x) >= 0 and (j + y) >= 0 and (i + x) < self.M and (j + y) < self.N:
                            if self.pole[i + x][j + y].mine == True:
                                around_mines += 1
                if self.pole[i][j].mine == True and around_mines > 0:
                    around_mines -= 1
                self.pole[i][j].around_mines = around_mines
                around_mines = 0

app = QApplication([])
window = MainWindow()
pole_game = GameField()
window.init()
pole_game.init()
window.show()
app.exec()


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import csv
import os
import time

from absl import flags
import absl.logging as _logging  # pylint: disable=unused-import
import tensorflow as tf

import imagenet_input
import resnet_model
from tensorflow.contrib import summary
from tensorflow.contrib.tpu.python.tpu import bfloat16
from tensorflow.contrib.tpu.python.tpu import tpu_config
from tensorflow.contrib.tpu.python.tpu import tpu_estimator
from tensorflow.contrib.tpu.python.tpu import tpu_optimizer
from tensorflow.contrib.training.python.training import evaluation
from tensorflow.python.estimator import estimator

FLAGS = flags.FLAGS

flags.DEFINE_bool(
    'use_tpu', True,
    help=('Use TPU to execute the model for training and evaluation. If'
          ' --use_tpu=false, will use whatever devices are available to'
          ' TensorFlow by default (e.g. CPU and GPU)'))

# Cloud TPU Cluster Resolvers
flags.DEFINE_string(
    'tpu', default=None,
    help='Name of the Cloud TPU for Cluster Resolvers. You must specify either '
    'this flag or --master.')

flags.DEFINE_string(
    'gcp_project', default=None,
    help='Project name for the Cloud TPU-enabled project. If not specified, we '
    'will attempt to automatically detect the GCE project from metadata.')

flags.DEFINE_string(
    'tpu_zone', default=None,
    help='GCE zone where the Cloud TPU is located in. If not specified, we '
    'will attempt to automatically detect the GCE project from metadata.')

# Model specific flags
flags.DEFINE_string(
    'data_dir', default=None,
    help=('The directory where the ImageNet input data is stored. Please see'
          ' the README.md for the expected data format.'))

flags.DEFINE_string(
    'model_dir', default=None,
    help=('The directory where the model and training/evaluation summaries are'
          ' stored.'))

flags.DEFINE_integer(
    'resnet_depth', default=50,
    help=('Depth of ResNet model to use. Must be one of {18, 34, 50, 101, 152,'
          ' 200}. ResNet-18 and 34 use the pre-activation residual blocks'
          ' without bottleneck layers. The other models use pre-activation'
          ' bottleneck layers. Deeper models require more training time and'
          ' more memory and may require reducing --train_batch_size to prevent'
          ' running out of memory.'))

flags.DEFINE_integer(
    'train_steps', default=112590,
    help=('The number of steps to use for training. Default is 112590 steps'
          ' which is approximately 90 epochs at batch size 1024. This flag'
          ' should be adjusted according to the --train_batch_size flag.'))

flags.DEFINE_integer(
    'train_batch_size', default=1024, help='Batch size for training.')

flags.DEFINE_integer(
    'eval_batch_size', default=1024, help='Batch size for evaluation.')

flags.DEFINE_integer(
    'steps_per_eval', default=1251,
    help=('Controls how often evaluation is performed. Since evaluation is'
          ' fairly expensive, it is advised to evaluate as infrequently as'
          ' possible (i.e. up to --train_steps, which evaluates the model only'
          ' after finishing the entire training regime).'))

flags.DEFINE_integer(
    'iterations_per_loop', default=1251,
    help=('Number of steps to run on TPU before outfeeding metrics to the CPU.'
          ' If the number of iterations in the loop would exceed the number of'
          ' train steps, the loop will exit before reaching'
          ' --iterations_per_loop. The larger this value is, the higher the'
          ' utilization on the TPU.'))

flags.DEFINE_integer(
    'num_parallel_calls', default=64,
    help=('Number of parallel threads in CPU for the input pipeline'))

flags.DEFINE_integer(
    'num_cores', default=None,
    help=('Number of TPU cores. For a single TPU device, this is 8 because each'
          ' TPU has 4 chips each with 2 cores.'))

flags.DEFINE_string('mode', 'train_and_eval',
                    'Mode to run: train or eval (default: train)')

flags.DEFINE_string(
    'data_format',
    default='channels_last',
    help=('A flag to override the data format used in the model. The value '
          'is either channels_first or channels_last. To run the network on '
          'CPU or TPU, channels_last should be used.'))

flags.DEFINE_string(
    'export_dir',
    default=None,
    help=('The directory where the exported SavedModel will be stored.'))

flags.DEFINE_bool(
    'use_transpose', True,
    help=('Use the TPU double transpose optimization'))

flags.DEFINE_bool(
    'enable_hostcall', True,
    help=('Use the TPU double transpose optimization'))

# Dataset constants
LABEL_CLASSES = 1000
NUM_TRAIN_IMAGES = 1281167
NUM_EVAL_IMAGES = 50000

# Learning hyperparameters
BASE_LEARNING_RATE = 0.1     # base LR when batch size = 256
MOMENTUM = 0.9
WEIGHT_DECAY = 1e-4
LR_SCHEDULE = [    # (multiplier, epoch to start) tuples
    (1.0, 5), (0.1, 30), (0.01, 60), (0.001, 80)
]

def learning_rate_schedule(current_epoch):
  """Handles linear scaling rule, gradual warmup, and LR decay.

  The learning rate starts at 0, then it increases linearly per step.
  After 5 epochs we reach the base learning rate (scaled to account
    for batch size).
  After 30, 60 and 80 epochs the learning rate is divided by 10.
  After 90 epochs training stops and the LR is set to 0. This ensures
    that we train for exactly 90 epochs for reproducibility.

  Args:
    current_epoch: `Tensor` for current epoch.

  Returns:
    A scaled `Tensor` for current learning rate.
  """
  scaled_lr = BASE_LEARNING_RATE * (FLAGS.train_batch_size / 256.0)

  decay_rate = (scaled_lr * LR_SCHEDULE[0][0] *
                current_epoch / LR_SCHEDULE[0][1])
  for mult, start_epoch in LR_SCHEDULE:
    decay_rate = tf.where(current_epoch < start_epoch,
                          decay_rate, scaled_lr * mult)
  return decay_rate

def resnet_model_fn(features, labels, mode, params):
  """The model_fn for ResNet to be used with TPUEstimator.

  Args:
    features: `Tensor` of batched images.
    labels: `Tensor` of labels for the data samples
    mode: one of `tf.estimator.ModeKeys.{TRAIN,EVAL}`
    params: `dict` of parameters passed to the model from the TPUEstimator,
        `params['batch_size']` is always provided and should be used as the
        effective batch size.

  Returns:
    A `TPUEstimatorSpec` for the model
  """
  if isinstance(features, dict):
    features = features['feature']

  # In most cases, the default data format NCHW instead of NHWC should be
  # used for a significant performance boost on GPU/TPU. NHWC should be used
  # only if the network needs to be run on CPU since the pooling operations
  # are only supported on NHWC.
  if FLAGS.data_format == 'channels_first':
    features = tf.transpose(features, [0, 3, 1, 2])

  if FLAGS.use_transpose:
    features = tf.transpose(features, [3, 0, 1, 2])  # HWCN to NHCW

  with bfloat16.bfloat16_scope():
    network = resnet_model.resnet_v1(
        resnet_depth=FLAGS.resnet_depth,
        num_classes=LABEL_CLASSES,
        data_format=FLAGS.data_format)

    logits = network(
        inputs=features, is_training=(mode == tf.estimator.ModeKeys.TRAIN))

    logits = tf.cast(logits, tf.float32)

  if mode == tf.estimator.ModeKeys.PREDICT:
    predictions = {
        'classes': tf.argmax(logits, axis=1),
        'probabilities': tf.nn.softmax(logits, name='softmax_tensor')
    }
    return tf.estimator.EstimatorSpec(
        mode=mode,
        predictions=predictions,
        export_outputs={
            'classify': tf.estimator.export.PredictOutput(predictions)
        })

  # If necessary, in the model_fn, use params['batch_size'] instead the batch
  # size flags (--train_batch_size or --eval_batch_size).
  batch_size = params['batch_size']   # pylint: disable=unused-variable

  # Calculate loss, which includes softmax cross entropy and L2 regularization.
  one_hot_labels = tf.one_hot(labels, LABEL_CLASSES)
  cross_entropy = tf.losses.softmax_cross_entropy(
      logits=logits, onehot_labels=one_hot_labels)

  # Add weight decay to the loss for non-batch-normalization variables.
  loss = cross_entropy + WEIGHT_DECAY * tf.add_n(
      [tf.nn.l2_loss(v) for v in tf.trainable_variables()
       if 'batch_normalization' not in v.name])

  host_call = None
  if mode == tf.estimator.ModeKeys.TRAIN:
    # Compute the current epoch and associated learning rate from global_step.
    global_step = tf.train.get_global_step()
    steps_per_epoch = NUM_TRAIN_IMAGES / FLAGS.train_batch_size
    current_epoch = (tf.cast(global_step, tf.float32) /
                     steps_per_epoch)
    learning_rate = learning_rate_schedule(current_epoch)

    optimizer = tf.train.MomentumOptimizer(
        learning_rate=learning_rate, momentum=MOMENTUM, use_nesterov=True)
    if FLAGS.use_tpu:
      # When using TPU, wrap the optimizer with CrossShardOptimizer which
      # handles synchronization details between different TPU cores. To the
      # user, this should look like regular synchronous training.
      optimizer = tpu_optimizer.CrossShardOptimizer(optimizer)

    # Batch normalization requires UPDATE_OPS to be added as a dependency to
    # the train operation.
    update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
    with tf.control_dependencies(update_ops):
      train_op = optimizer.minimize(loss, global_step)

    # To log the loss, current learning rate, and epoch for Tensorboard, the
    # summary op needs to be run on the host CPU via host_call. host_call
    # expects [batch_size, ...] Tensors, thus reshape to introduce a batch
    # dimension. These Tensors are implicitly broadcasted to
    # [params['batch_size'], ].
    gs_t = tf.reshape(tf.cast(global_step, tf.int32), [1])
    loss_t = tf.reshape(loss, [1])
    lr_t = tf.reshape(learning_rate, [1])
    ce_t = tf.reshape(current_epoch, [1])

    def host_call_fn(gs, loss, lr, ce):
      """Training host call. Creates scalar summaries for training metrics.

      This function is executed on the CPU and should not directly reference
      any Tensors in the rest of the `model_fn`. To pass Tensors from the model
      to the `metric_fn`, provide as part of the `host_call`. See
      https://www.tensorflow.org/api_docs/python/tf/contrib/tpu/TPUEstimatorSpec
      for more information.

      Arguments should match the list of `Tensor` objects passed as the second
      element in the tuple passed to `host_call`.

      Args:
        gs: `Tensor with shape `[batch, ]` for the global_step
        loss: `Tensor` with shape `[batch, ]` for the training loss.
        lr: `Tensor` with shape `[batch, ]` for the learning_rate.
        ce: `Tensor` with shape `[batch, ]` for the current_epoch.

      Returns:
        List of summary ops to run on the CPU host.
      """
      # Outfeed supports int32 but global_step is expected to be int64.
      gs = tf.cast(tf.reduce_mean(gs), tf.int64)
      with summary.create_file_writer(FLAGS.model_dir).as_default():
        with summary.always_record_summaries():
          summary.scalar('loss', tf.reduce_mean(loss), step=gs)
          summary.scalar('learning_rate', tf.reduce_mean(lr), step=gs)
          summary.scalar('current_epoch', tf.reduce_mean(ce), step=gs)

          return summary.all_summary_ops()

    if FLAGS.enable_hostcall:
      host_call = (host_call_fn, [gs_t, loss_t, lr_t, ce_t])

  else:
    train_op = None

  eval_metrics = None
  if mode == tf.estimator.ModeKeys.EVAL:
    def metric_fn(labels, logits):
      """Evaluation metric function. Evaluates accuracy.

      This function is executed on the CPU and should not directly reference
      any Tensors in the rest of the `model_fn`. To pass Tensors from the model
      to the `metric_fn`, provide as part of the `eval_metrics`. See
      https://www.tensorflow.org/api_docs/python/tf/contrib/tpu/TPUEstimatorSpec
      for more information.

      Arguments should match the list of `Tensor` objects passed as the second
      element in the tuple passed to `eval_metrics`.

      Args:
        labels: `Tensor` with shape `[batch, ]`.
        logits: `Tensor` with shape `[batch, num_classes]`.

      Returns:
        A dict of the metrics to return from evaluation.
      """
      predictions = tf.argmax(logits, axis=1)
      top_1_accuracy = tf.metrics.accuracy(labels, predictions)
      in_top_5 = tf.cast(tf.nn.in_top_k(logits, labels, 5), tf.float32)
      top_5_accuracy = tf.metrics.mean(in_top_5)

      return {
          'top_1_accuracy': top_1_accuracy,
          'top_5_accuracy': top_5_accuracy,
      }

    eval_metrics = (metric_fn, [labels, logits])

  return tpu_estimator.TPUEstimatorSpec(
      mode=mode,
      loss=loss,
      train_op=train_op,
      host_call=host_call,
      eval_metrics=eval_metrics)

def main(unused_argv):
  tpu_cluster_resolver = tf.contrib.cluster_resolver.TPUClusterResolver(
      FLAGS.tpu,
      zone=FLAGS.tpu_zone,
      project=FLAGS.gcp_project)

  config = tpu_config.RunConfig(
      cluster=tpu_cluster_resolver,
      model_dir=FLAGS.model_dir,
      save_checkpoints_steps=FLAGS.iterations_per_loop,
      keep_checkpoint_max=None,
      tpu_config=tpu_config.TPUConfig(
          iterations_per_loop=FLAGS.iterations_per_loop,
          num_shards=FLAGS.num_cores,
          per_host_input_for_training=tpu_config.InputPipelineConfig.PER_HOST_V2
      ))

  resnet_classifier = tpu_estimator.TPUEstimator(
      use_tpu=FLAGS.use_tpu,
      model_fn=resnet_model_fn,
      config=config,
      train_batch_size=FLAGS.train_batch_size,
      eval_batch_size=FLAGS.eval_batch_size)

  # Input pipelines are slightly different (with regards to shuffling and
  # preprocessing) between training and evaluation.
  imagenet_train = imagenet_input.ImageNetInput(
      is_training=True,
      data_dir=FLAGS.data_dir,
      num_parallel_calls=FLAGS.num_parallel_calls,
      use_transpose=FLAGS.use_transpose)
  imagenet_eval = imagenet_input.ImageNetInput(
      is_training=False,
      data_dir=FLAGS.data_dir,
      num_parallel_calls=FLAGS.num_parallel_calls,
      use_transpose=FLAGS.use_transpose)

  current_step = estimator._load_global_step_from_checkpoint_dir(FLAGS.model_dir)  # pylint: disable=protected-access,line-too-long
  steps_per_epoch = NUM_TRAIN_IMAGES // FLAGS.train_batch_size
  start_timestamp = time.time()
  current_epoch = current_step // steps_per_epoch

  if FLAGS.mode == 'train':
    resnet_classifier.train(
        input_fn=imagenet_train.input_fn, max_steps=FLAGS.train_steps)
    training_time = time.time() - start_timestamp
    tf.logging.info('Finished training in %d seconds' % training_time)

    with tf.gfile.GFile(FLAGS.model_dir + '/total_time_%s.txt' % training_time, 'w') as f:  # pylint: disable=line-too-long
      f.write('Total training time was %s seconds' % training_time)

  elif FLAGS.mode == 'eval':
    results = []

    # Run evaluation when there's a new checkpoint
    for ckpt in evaluation.checkpoints_iterator(FLAGS.model_dir):
      tf.logging.info('Starting to evaluate.')
      try:
        start_timestamp = time.time()  # This time will include compilation time
        eval_results = resnet_classifier.evaluate(
            input_fn=imagenet_eval.input_fn,
            steps=NUM_EVAL_IMAGES // FLAGS.eval_batch_size,
            checkpoint_path=ckpt)
        elapsed_time = int(time.time() - start_timestamp)
        tf.logging.info('Eval results: %s. Elapsed seconds: %d' %
                        (eval_results, elapsed_time))

        current_step = int(os.path.basename(ckpt).split('-')[1])
        current_epoch = current_step // steps_per_epoch
        results.append([
            current_epoch,
            '{0:.2f}'.format(eval_results['top_1_accuracy']*100),
            '{0:.2f}'.format(eval_results['top_5_accuracy']*100),
        ])

        # Terminate eval job when final checkpoint is reached
        if current_step >= FLAGS.train_steps:
          tf.logging.info(
              'Evaluation finished after training step %d' % current_step)
          break

      except tf.errors.NotFoundError:
        # Since the coordinator is on a different job than the TPU worker,
        # sometimes the TPU worker does not finish initializing until long after
        # the CPU job tells it to start evaluating. In this case, the checkpoint
        # file could have been deleted already.
        tf.logging.info(
            'Checkpoint %s no longer exists, skipping checkpoint' % ckpt)

    with tf.gfile.GFile(FLAGS.model_dir + '/epoch_results_eval.tsv', 'wb') as tsv_file:  # pylint: disable=line-too-long
      writer = csv.writer(tsv_file, delimiter='\t')
      writer.writerow(['epoch', 'top1Accuracy', 'top5Accuracy'])
      writer.writerows(results)

  elif FLAGS.mode == 'train_and_eval':
    results = []
    while current_epoch < 95:
      next_checkpoint = (current_epoch + 1) * steps_per_epoch
      resnet_classifier.train(
          input_fn=imagenet_train.input_fn, max_steps=next_checkpoint)
      current_epoch += 1

      tf.logging.info('Finished training up to step %d. Elapsed seconds %d.' %
                      (next_checkpoint, int(time.time() - start_timestamp)))

      # Evaluate the model on the most recent model in --model_dir.
      # Since evaluation happens in batches of --eval_batch_size, some images
      # may be excluded modulo the batch size. As long as the batch size is
      # consistent, the evaluated images are also consistent.
      tf.logging.info('Starting to evaluate.')
      eval_results = resnet_classifier.evaluate(
          input_fn=imagenet_eval.input_fn,
          steps=NUM_EVAL_IMAGES // FLAGS.eval_batch_size)
      tf.logging.info('Eval results: %s' % eval_results)

      elapsed_time = int(time.time() - start_timestamp)
      tf.logging.info('Finished epoch %s at %s time' % (
          current_epoch, elapsed_time))
      results.append([
          current_epoch,
          elapsed_time / 3600.0,
          '{0:.2f}'.format(eval_results['top_1_accuracy']*100),
          '{0:.2f}'.format(eval_results['top_5_accuracy']*100),
      ])

    with tf.gfile.GFile(FLAGS.model_dir + '/epoch_results_train_eval.tsv', 'wb') as tsv_file:   # pylint: disable=line-too-long
      writer = csv.writer(tsv_file, delimiter='\t')
      writer.writerow(['epoch', 'hours', 'top1Accuracy', 'top5Accuracy'])
      writer.writerows(results)
  else:
    tf.logging.info('Mode not found.')

  if FLAGS.export_dir is not None:
    # The guide to serve a exported TensorFlow model is at:
    #    https://www.tensorflow.org/serving/serving_basic
    tf.logging.info('Starting to export model.')
    resnet_classifier.export_savedmodel(
        export_dir_base=FLAGS.export_dir,
        serving_input_receiver_fn=imagenet_input.image_serving_input_fn)

if __name__ == '__main__':
  tf.logging.set_verbosity(tf.logging.INFO)
  tf.app.run()


import numpy as np
from lime import lime_tabular

from ...base import Explainer

class LimeExplainer(Explainer):
    def __init__(self, train_ds, labels, *args, meta_prefix=None, **kwargs) -> None:
        super().__init__(*args, meta_prefix=meta_prefix, **kwargs)

        data = np.array([item["item"] for item in train_ds])
        self._explainer = lime_tabular.LimeTabularExplainer(
            data, feature_selection="none", training_labels=labels
        )
        self._labels = labels

    def predict(self, x, model):
        if not hasattr(model, "predict_proba"):
            raise ValueError("The model should have `predict_proba` method")

        explanations = []
        for item in x:
            ex = self._explainer.explain_instance(
                item,
                model.predict_proba,
                labels=self._labels,
                num_features=len(self._labels),
            )
            predicted_label = np.argmax(ex.predict_proba)
            ex = ex.as_map()[predicted_label]
            # Sorts by the feature order
            importance_scores = [item[1] for item in sorted(ex)]
            explanations.append(importance_scores)
        return np.asarray(explanations)


import sys
import time
import traceback
import discord
from os import getenv
from discord import Game, File
from discord.ext import commands
from discord.utils import get
import logging
import re
from urllib.parse import urlparse
from collections import defaultdict
from sqlalchemy import create_engine, func, update, sql
from sqlalchemy.orm import sessionmaker
from models import Base, Battles, Participants
from datetime import datetime, timezone, timedelta
import math as m
import pandas as pd
import numpy as np

# Server IDs
FRICKS_SERVER_ID = "Placeholder"
CLAP_SERVER_ID = "Placeholder"
KINGSMEN_SERVER_ID = "Placeholder"
OOV_SERVER_ID ="Placeholder"
PING_SERVER_ID ="Placeholder"
FAME_SERVER_ID = "Placeholder"
TEST_SERVER_ID ="Placeholder"
MC_SERVER_ID = "Placeholder"

# User IDs
PUPPYBOT_ID = "Placeholder"

# Channel IDs
BOT_TESTING_CHANNEL_ID = "Placeholder"
GENERAL_CHANNEL_ID = "Placeholder"
SCREENSHOT_APPROVAL_CHANNEL_ID = "Placeholder"
SCREENSHOT_LOG_CHANNEL_ID = "Placeholder"
FUNDS_TRACKING_CHANNEL_ID = "Placeholder"
RECRUITMENT_CHANNEL_ID = "Placeholder"
LOGS_CHANNEL_ID = "Placeholder"
LOOT_SPLIT_CHANNEL_ID = "Placeholder"
# Role IDs
FRICKS_ROLE_ID =  "Placeholder"
KINGSMEN_ROLE_ID = "Placeholder"
SOLDIER_ROLE_ID = "Placeholder"
OOV_ROLE_ID = "Placeholder"
PING_ROLE_ID =  "Placeholder"
FAME_ROLE_ID = "Placeholder"
NKC_ROLE_ID = "Placeholder"
NKC_RECRUIT_ROLE_ID = "Placeholder"
NKC_RED_ROLE_ID = "Placeholder"
NKC_GREEN_ROLE_ID = "Placeholder"
NKC_BLUE_ROLE_ID = "Placeholder"
AK_ROLE_ID = "Placeholder"
AK_RECRUIT_ROLE_ID = "Placeholder"
DARK_ROLE_ID = "Placeholder"
MC_ROLE_ID = "Placeholder"
MC_ROLE_ELITE_ID = "Placeholder"
# Role CLAP id's
FRICKLING_ROLE_ID = "Placeholder"
FRICKS_CLAP_ROLE_ID = "Placeholder"
KINGSMEN_CLAP_ROLE_ID = "Placeholder"
OOV_CLAP_ROLE_ID = "Placeholder"
PING_CLAP_ROLE_ID = "Placeholder"
FAME_CLAP_ROLE_ID = "Placeholder"
ROYAL_CLAP_ROLE_ID = "Placeholder"
AK_CLAP_ROLE_ID = "Placeholder"
DARK_CLAP_ROLE_ID = "Placeholder"
GUEST_CLAP_ROLE_ID = "Placeholder"
ROYAL_SERVER_ID = "Placeholder"
AK_SERVER_ID = "Placeholder"
DARK_SERVER_ID = "Placeholder"
MC_CLAP_ROLE_ID = "Placeholder"

intents = discord.Intents.default()
intents.members = True

client = commands.Bot(command_prefix='%', case_insensitive=True, chunk_guilds_at_startup = True, intents=intents)

engine = create_engine('sqlite:///register.db')
Base.metadata.bind = engine
DBSession = sessionmaker(bind=engine)
session = DBSession()

def is_url(x):
    try:
        result = urlparse(x)
        return all([result.scheme, result.netloc, result.path])
    except:
        return False

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s:%(levelname)s:%(name)s: %(message)s',
    filename="fricksbot.log",
    filemode='a'
)

# Discord Logger
logger = logging.getLogger('discord')
logger.setLevel(logging.INFO)

def role_check(user, roles):
    role_list = []

    for role in user.roles:
        role_list.append(role.id)

    return any(i in roles for i in role_list)

def find_between(s, first, last):
    try:
        start_idx = s.index(first) + len(first)
        end_idx = s.index(last, start_idx)
        return s[start_idx:end_idx]
    except ValueError:
        return ""

def getBattleTimer(time):
    hour = time.hour

    if hour in (23, 0, 1):
        return 0
    elif hour in (2,3):
        return 3
    elif hour in (4,5,6):
        return 5
    if hour in (11, 12, 13):
        return 12
    if hour in (14,15,16):
        return 15
    if hour in (17, 18, 19):
        return 18
    elif hour in (20,21,22):
        return 21

@client.event
async def on_ready():
    channel = client.get_channel(BOT_TESTING_CHANNEL_ID)
    await client.change_presence(activity=Game('Granting permissions, 24/7'))

@client.command()
async def mc(ctx):
    message = ctx.message
    if ctx.guild and ctx.guild.id == TEST_SERVER_ID:
        mc_server = client.get_guild(MC_SERVER_ID)
        mc_member = mc_server.get_member(message.author.id)

        if mc_member is None:
            await message.channel.send("You are not in MC guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🗡')
            return

        roles = [MC_ROLE_ID, MC_ROLE_ELITE_ID]
        if role_check(mc_member, roles):
            role = get(message.guild.roles, id=MC_CLAP_ROLE_ID)
            rrole = get(message.guild.roles, id=GUEST_CLAP_ROLE_ID)
            await message.author.add_roles(role)
            await message.channel.send("You are in MC guild granting permissions")
            await message.add_reaction('👌')
            await message.author.remove_roles(rrole)
        else:
            await message.channel.send("You are not in MC guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🕵')
            await message.add_reaction('❌')
    else:
        await message.channel.send("Wrong server, bud. You can only use this command in the CLAP discord.")

@client.command()
async def nkc(ctx):
    message = ctx.message
    if ctx.guild and ctx.guild.id == TEST_SERVER_ID:
        royal_server = client.get_guild(ROYAL_SERVER_ID)
        royal_member = royal_server.get_member(message.author.id)

        if royal_member is None:
            await message.channel.send("You are not in NKC guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🗡')
            return

        roles = [NKC_ROLE_ID, NKC_RECRUIT_ROLE_ID, NKC_RED_ROLE_ID, NKC_GREEN_ROLE_ID, NKC_BLUE_ROLE_ID]
        if role_check(royal_member, roles):
            role = get(message.guild.roles, id=ROYAL_CLAP_ROLE_ID)
            rrole = get(message.guild.roles, id=GUEST_CLAP_ROLE_ID)
            await message.author.add_roles(role)
            await message.channel.send("You are in NKC guild granting permissions")
            await message.add_reaction('👌')
            await message.author.remove_roles(rrole)
        else:
            await message.channel.send("You are not in NKC guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🕵')
            await message.add_reaction('❌')
    else:
        await message.channel.send("Wrong server, bud. You can only use this command in the CLAP discord.")

@client.command()
async def dark(ctx):
    message = ctx.message
    if ctx.guild and ctx.guild.id == TEST_SERVER_ID:
        dark_server = client.get_guild(DARK_SERVER_ID)
        dark_member = dark_server.get_member(message.author.id)

        if dark_member is None:
            await message.channel.send("You are not in TheDarkClan guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🗡')
            return

        roles = [DARK_ROLE_ID]
        if role_check(dark_member, roles):
            role = get(message.guild.roles, id=DARK_CLAP_ROLE_ID)
            rrole = get(message.guild.roles, id=GUEST_CLAP_ROLE_ID)
            await message.author.add_roles(role)
            await message.channel.send("You are in TheDarkClan guild granting permissions")
            await message.add_reaction('👌')
            await message.author.remove_roles(rrole)
        else:
            await message.channel.send("You are not in TheDarkClan guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🕵')
            await message.add_reaction('❌')
    else:
        await message.channel.send("Wrong server, bud. You can only use this command in the CLAP discord.")

@client.command()
async def ak(ctx):
    message = ctx.message
    if ctx.guild and ctx.guild.id == TEST_SERVER_ID:
        ak_server = client.get_guild(AK_SERVER_ID)
        ak_member = ak_server.get_member(message.author.id)

        if ak_member is None:
            await message.channel.send("You are not in AK7 guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🗡')
            return

        roles = [AK_ROLE_ID, AK_RECRUIT_ROLE_ID]
        if role_check(ak_member, roles):
            role = get(message.guild.roles, id=AK_CLAP_ROLE_ID)
            rrole = get(message.guild.roles, id=GUEST_CLAP_ROLE_ID)
            await message.author.add_roles(role)
            await message.channel.send("You are in AK7 guild granting permissions")
            await message.author.remove_roles(rrole)
            await message.add_reaction('👌')
        else:
            await message.channel.send("You are not in AK7 guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🕵')
            await message.add_reaction('❌')
    else:
        await message.channel.send("Wrong server, bud. You can only use this command in the CLAP discord.")

@client.command()
async def oov(ctx):
    message = ctx.message
    if ctx.guild and ctx.guild.id == TEST_SERVER_ID:
        oov_server = client.get_guild(OOV_SERVER_ID)
        oov_member = oov_server.get_member(message.author.id)

        if oov_member is None:
            await message.channel.send("You are not in Oath of Vengeance guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🗡')
            return

        roles = [OOV_ROLE_ID]
        if role_check(oov_member, roles):
            role = get(message.guild.roles, id=OOV_CLAP_ROLE_ID)
            rrole = get(message.guild.roles, id=GUEST_CLAP_ROLE_ID)
            await message.author.add_roles(role)
            await message.author.remove_roles(rrole)
            await message.channel.send("You are in Oath of Vengeance guild granting permissions")
            await message.add_reaction('👌')
        else:
            await message.channel.send("You are not in Oath of Vengeance guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🕵')
            await message.add_reaction('❌')
    else:
        await message.channel.send("Wrong server, bud. You can only use this command in the CLAP discord.")

@client.command()
async def fricks(ctx):
    message = ctx.message
    if ctx.guild and ctx.guild.id == TEST_SERVER_ID:
        fricks_server = client.get_guild(FRICKS_SERVER_ID)
        fricks_member = fricks_server.get_member(message.author.id)

        if fricks_member is None:
            await message.channel.send("You are not in Fricks guild, permission not granted")
            return

        roles = [FRICKS_ROLE_ID, FRICKLING_ROLE_ID]
        if role_check(fricks_member, roles):
            role = get(message.guild.roles, id=FRICKS_CLAP_ROLE_ID)
            rrole = get(message.guild.roles, id=GUEST_CLAP_ROLE_ID)
            await message.channel.send("You are in Fricks guild, permission granted")
            await message.author.add_roles(role)
            await message.author.remove_roles(rrole)
        else:
            await message.channel.send("You are not in Fricks guild, permission not granted")

    else:
        await message.channel.send("Wrong server, bud. You can only use this command in the CLAP discord.")

@client.command()
async def kingsmen(ctx):
    message = ctx.message
    if ctx.guild and ctx.guild.id == TEST_SERVER_ID:
        kingsmen_server = client.get_guild(KINGSMEN_SERVER_ID)
        kingsmen_member = kingsmen_server.get_member(message.author.id)

        if kingsmen_member is None:
            await message.channel.send("You are not in TheKingsmen guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🗡')
            return

        roles = [KINGSMEN_ROLE_ID, SOLDIER_ROLE_ID]
        if role_check(kingsmen_member, roles):
            role = get(message.guild.roles, id=KINGSMEN_CLAP_ROLE_ID)
            rrole = get(message.guild.roles, id=GUEST_CLAP_ROLE_ID)
            await message.author.add_roles(role)
            await message.channel.send("You are in TheKingsmen guild granting permissions")
            await message.author.remove_roles(rrole)
            await message.add_reaction('👌')
        else:
            await message.channel.send("You are not in TheKingsmen guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🕵')
            await message.add_reaction('❌')
    else:
        await message.channel.send("Wrong server, bud. You can only use this command in the CLAP discord.")

@client.command()
async def ping(ctx):
    message = ctx.message
    if ctx.guild and ctx.guild.id == TEST_SERVER_ID:
        ping_server = client.get_guild(PING_SERVER_ID)
        ping_member = ping_server.get_member(message.author.id)

        if ping_member is None:
            await message.channel.send("You are not in Always350PinG guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🗡')
            return

        roles = [PING_ROLE_ID]
        if role_check(ping_member, roles):
            role = get(message.guild.roles, id=PING_CLAP_ROLE_ID)
            rrole = get(message.guild.roles, id=GUEST_CLAP_ROLE_ID)
            await message.author.add_roles(role)
            await message.channel.send("You are in Always350PinG guild granting permissions")
            await message.author.remove_roles(rrole)
            await message.add_reaction('👌')
        else:
            await message.channel.send("You are not in Always350PinG guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🕵')
            await message.add_reaction('❌')
    else:
        await message.channel.send("Wrong server, bud. You can only use this command in the CLAP discord.")

@client.command()
async def fame(ctx):
    message = ctx.message
    if ctx.guild and ctx.guild.id == TEST_SERVER_ID:
        fame_server = client.get_guild(FAME_SERVER_ID)
        fame_member = fame_server.get_member(message.author.id)

        if fame_member is None:
            await message.channel.send("You are not in F A M E L E S S guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🗡')
            return

        roles = [FAME_ROLE_ID]
        if role_check(fame_member, roles):
            role = get(message.guild.roles, id=FAME_CLAP_ROLE_ID)
            rrole = get(message.guild.roles, id=GUEST_CLAP_ROLE_ID)
            await message.author.add_roles(role)
            await message.channel.send("You are in F A M E L E S S guild granting permissions")
            await message.add_reaction('👌')
            await message.author.remove_roles(rrole)
        else:
            await message.channel.send("You are not in F A M E L E S S guild, permission not granted")
            await message.add_reaction('🐀')
            await message.add_reaction('🕵')
            await message.add_reaction('❌')
    else:
        await message.channel.send("Wrong server, bud. You can only use this command in the CLAP discord.")

client.run("Placeholder_BOT_TOKEN_HERE")


import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

img = cv.imread('tower.jpg', cv.IMREAD_GRAYSCALE)
img_data = []
rows, cols = img.shape

img_data.append(str(rows%256))
img_data.append(str(rows//256))

img_data.append(str(cols%256))
img_data.append(str(cols//256))

for row in range(rows):
	for col in range(cols):
		img_data.append(str(img[row][col]))

cv.imshow('image',img)
cv.waitKey(1000)

line_no = 0

while(True):
	f = open("updates.txt", "r")
	lines = f.readlines()
	while(line_no < len(lines)):
		coordinate, value = lines[line_no][:-1].split(' ')
		line_no += 1
		coordinate = int(coordinate) - 4
		value = int(value)
		try:
			img[coordinate//400][coordinate%400] = value
		except:
			pass
	cv.imshow('image',img)
	cv.waitKey(1)
cv.destroyAllWindows()