diff --git a/api.py b/api.py index 8fa8145..eb5f9a4 100644 --- a/api.py +++ b/api.py @@ -1,5 +1,7 @@ from fastapi import FastAPI, HTTPException from pydantic import BaseModel +from datetime import datetime, timedelta +from statistics import median # Fix 3.3 + 0.15 = 3.4499999999999997 from decimal import Decimal as d @@ -19,6 +21,23 @@ def token_check(token): else: return False +def stat_run(cdm_change): + stat = read('stat.json') + date = datetime.today().strftime('%Y-%m-%d') + if date in stat: + stat[date]['gbal'] += cdm_change + write(stat, 'stat.json') + else: + db = read() + bal = 0 + for id in db['id']: + bal += db['id'][id]['bal'] + stat[date] = {'gbal': bal, 'time2cdm': 0} + write(stat, 'stat.json') + +def format_sign(number): + return f"+{number}" if number > 0 else f"{number}" + class User_in_db(BaseModel): token: str id: str = None @@ -74,7 +93,7 @@ def user_add(it: User_add): print(id) if token_check(token): db = read() - db['id'][id] = {'tg': tg, 'ds': ds, 'mine': mine, 'nick': nick, 'passwd': passwd, 'bal': 0.0} + db['id'][id] = {'tg': tg, 'ds': ds, 'mine': mine, 'nick': nick, 'passwd': passwd, 'bal': 0.0, 'time': 0} db['nick'][nick] = id if tg: db['tg'][tg] = id @@ -120,6 +139,7 @@ def coins_add(it: Coins_add): db = read() db['id'][id]['bal'] = fix_add(db['id'][id]['bal'], amount) write(db) + stat_run(amount) return 'OK' else: return 'Error' @@ -135,6 +155,7 @@ def coins_del(it: Coins_del): db = read() db['id'][id]['bal'] = fix_sub(db['id'][id]['bal'], amount) write(db) + stat_run(amount*-1) return 'OK' else: return 'Error' @@ -257,7 +278,7 @@ class Update_passwd(BaseModel): id: str passwd: str @app.post('/api/update_passwd/') -def update_tg(it: Update_passwd): +def update_passwd(it: Update_passwd): token, id, passwd = it.token, it.id, it.passwd if token_check(token): db = read() @@ -267,6 +288,37 @@ def update_tg(it: Update_passwd): else: return 'Error' +class Update_time(BaseModel): + token: str + id: str + time: str +@app.post('/api/update_time/') +def update_time(it: Update_time): + token, id, time = it.token, it.id, int(it.time) + if token_check(token): + db = read() + db['id'][id]['time'] = time + write(db) + return 'OK' + else: + return 'Error' + + +class Add_time(BaseModel): + token: str + id: str + time: str +@app.post('/api/add_time/') +def add_time(it: Add_time): + token, id, time = it.token, it.id, int(it.time) + if token_check(token): + db = read() + db['id'][id]['time'] += time + write(db) + return 'OK' + else: + return 'Error' + class Check_bal(BaseModel): token: str @@ -340,6 +392,66 @@ def get_passwd(it: Get_passwd): else: return 'Error' +class Get_time(BaseModel): + token: str + id: str +@app.post('/api/get_time/') +def get_time(it: Get_time): + token, id = it.token, it.id + if token_check(token): + db = read() + return db['id'][id]['time'] + else: + return 'Error' + +class Get_stat(BaseModel): + token: str +@app.post('/api/get_stat/') +def get_stat(it: Get_stat): + token = it.token + if token_check(token): + # Общий баланс, среднее значение, медиана + # Низшее значение, высшее значение + # Изменение баланса и time2cdm + # Прирост за счёт алмазов, за счёт time2cdm + stat_run(0) + stats = {'gbal': 0, 'average': 0, 'median': 0, 'time2cdm': 0, + 'gbal_delta': '0', 'time2cdm_delta': '', + 'min': 0, 'max': 0, + 'up_diamond': 0, 'up_time2cdm': 0} + + stat = read('stat.json') + date = datetime.today().strftime('%Y-%m-%d') + yesterday = (datetime.today() - timedelta(days=1)).strftime('%Y-%m-%d') + if yesterday in stat: + gbal_y = stat[yesterday]['gbal'] + time2cdm_y = stat[yesterday]['time2cdm'] + else: + gbal_y, time2cdm_y = 0, 0 + gbal = stat[date]['gbal'] + time2cdm = stat[date]['time2cdm'] + + # Получаем все балансы + db = read() + bals = [] + for id in db['id']: + bals.append(db['id'][id]['bal']) + + # Заполняем данные + stats['gbal'] = round(gbal, 3) + stats['average'] = round(sum(bals)/len(bals), 3) + stats['median'] = round(median(bals), 3) + stats['time2cdm'] = round(time2cdm, 3) + stats['gbal_delta'] = format_sign(round(gbal-gbal_y, 3)) + stats['time2cdm_delta'] = format_sign(round(time2cdm-time2cdm_y, 3)) + stats['min'] = round(min([x for x in bals if x != 0]), 3) + stats['max'] = round(max(bals), 3) + stats['up_diamond'] = round(gbal - (gbal_y + time2cdm + time2cdm_y), 3) + + return stats + else: + return 'Error' + # TODO: unauth from account if __name__ == '__main__': diff --git a/call2api.py b/call2api.py index 5102248..0d71651 100644 --- a/call2api.py +++ b/call2api.py @@ -1,5 +1,5 @@ from requests import post -from json import dumps +from json import dumps, loads from xxhash import xxh32 from db import * @@ -11,14 +11,20 @@ def hash(text): text = str(text) return xxh32(text).hexdigest() -def call(api_url, data, pre=True): +def call(api_url, data, pre=True, fix=True): if pre: response = post(url_pre + api_url, data=dumps(data)) else: response = post(api_url, data=dumps(data)) - print(response.status_code) - print(response.text) - return response.text.replace('"', '') + #print(response.status_code) + #print(response.text) + try: + if fix: + return response.text.replace('"', '') + else: + return response.text + except: + return response.text def user_in_db(token, id=None, tg=None, ds=None, mine=None, nick=None): data = {'token': token} @@ -86,6 +92,10 @@ def update_passwd(token, id, passwd): data = {'token': token, 'id': id, 'passwd': hash(passwd)} return call('api/update_passwd/', data) +def update_time(token, id, time): + data = {'token': token, 'id': id, 'time': time} + return call('api/update_time/', data) + def check_bal(token, id): data = {'token': token, 'id': id} @@ -96,20 +106,28 @@ def get_nick(token, id): return call('api/get_nick/', data) def get_tg(token, id): - data = {'token': token, 'id': id} - return call('api/get_tg/', data) + data = {'token': token, 'id': id} + return call('api/get_tg/', data) def get_ds(token, id): - data = {'token': token, 'id': id} - return call('api/get_ds/', data) + data = {'token': token, 'id': id} + return call('api/get_ds/', data) def get_mine(token, id): - data = {'token': token, 'id': id} - return call('api/get_mine/', data) + data = {'token': token, 'id': id} + return call('api/get_mine/', data) def get_passwd(token, id): - data = {'token': token, 'id': id} - return call('api/get_passwd/', data) + data = {'token': token, 'id': id} + return call('api/get_passwd/', data) + +def get_time(token, id): + data = {'token': token, 'id': id} + return call('api/get_time/', data) + +def get_stat(token): + data = {'token': token} + return loads(call('api/get_stat/', data, fix=False)) def transfer_callback(addr, token, src_nick, dst_nick, amount): amount = str(amount) diff --git a/db.py b/db.py index 9eb606b..ef1e3d6 100644 --- a/db.py +++ b/db.py @@ -15,13 +15,25 @@ if not os.path.exists('db.json'): if not os.path.exists('conf.json'): db = {'api_token': 'None', - 'tg_token': 'None', - 'ds_token': 'None'} + 'tg_token': 'None', + 'ds_token': 'None', + 'push_src_nick': 0, + 'push_id': 0, + 'push_amount': 0, + 'time2cdm': 0, + 'owner': 0} js = json.dumps(db, indent=2) with open("conf.json", "w") as outfile: outfile.write(js) print('Created new conf.json') +if not os.path.exists('stat.json'): + db = {} + js = json.dumps(db, indent=2) + with open("stat.json", "w") as outfile: + outfile.write(js) + print('Created new stat.json') + def read(file = 'db.json'): with open(file, "r", encoding="utf-8") as openfile: db = json.load(openfile) diff --git a/ds.py b/ds.py index 39e5df7..673d54d 100644 --- a/ds.py +++ b/ds.py @@ -86,16 +86,21 @@ async def help(message): /nick ник - Смена ника /bal - Баланс /pay ник сумма - Перевод +/time2cdm - Конвертация времени на сервере в CDM +/stats - Статистика ` ''') async def bal(message): - send = message.channel.send - if await checkauth(message): - id = user_in_db(API_TOKEN, ds=message.author.id) - coins = check_bal(API_TOKEN, id) - nick = get_nick(API_TOKEN, id) - await send(f'''Ваш баланс: `{coins}` CDM + send = message.channel.send + if await checkauth(message): + id = user_in_db(API_TOKEN, ds=message.author.id) + coins = check_bal(API_TOKEN, id) + nick = get_nick(API_TOKEN, id) + time = int(get_time(API_TOKEN, id)) + hours = time//3600 ; minutes = (time - hours*3600)//60 + await send(f'''Ваш баланс: `{coins}` CDM +Время на сервере: `{f"{hours}:{minutes}"}` Ник: `{nick}`''') @@ -207,23 +212,58 @@ async def pay(message): else: await send('/pay ник количество') +async def time2cdm(message): + send = message.channel.send + if await checkauth(message): + id = user_in_db(API_TOKEN, ds=message.author.id) + course = read('conf.json')['time2cdm'] + time = int(get_time(API_TOKEN, id)) + amount = time*course + if update_time(API_TOKEN, id, '0'): + if coins_add(API_TOKEN, id, str(amount)): + await send(f'''Вы успешно конвертировали время на сервере в `{str(amount)}` CDM.''') + +async def stats(message): + send = message.channel.send + if await checkauth(message): + data = get_stat(API_TOKEN) + bal = f'Баланс ({data["gbal_delta"]})' + t2cdm = f'Time2cdm ({data["time2cdm_delta"]})' + max_len = max(len(bal), len(t2cdm), 19) + await send(f'''```json +{bal.ljust(max_len)}: {data["gbal"]} +{t2cdm.ljust(max_len)}: {data["time2cdm"]} + +Среднее значение : {data["average"]} +Медиана : {data["median"]} +Минимум : {data["min"]} +Максимум : {data["max"]} + +Ввод/вывод алмазов : {data["up_diamond"]} +``` +''') + @bot.event async def on_message(message): - send = message.channel.send - if command('help', message): - await help(message) - elif command('reg', message): - await reg(message) - elif command('login', message): - await login(message) - elif command('unreg', message): - await unreg(message) - elif command('bal', message): - await bal(message) - elif command('passwd', message): - await passwd(message) - elif command('pay', message): - await pay(message) + send = message.channel.send + if command('help', message): + await help(message) + elif command('reg', message): + await reg(message) + elif command('login', message): + await login(message) + elif command('unreg', message): + await unreg(message) + elif command('bal', message): + await bal(message) + elif command('passwd', message): + await passwd(message) + elif command('pay', message): + await pay(message) + elif command('time2cdm', message): + await time2cdm(message) + elif command('stats', message): + await stats(message) # API для переводов TG->DS / ... diff --git a/tg.py b/tg.py index 23a5711..33f7b58 100644 --- a/tg.py +++ b/tg.py @@ -63,6 +63,8 @@ def help(message): /nick ник - Смена ника /bal - Баланс /pay ник сумма - Перевод +/time2cdm - Конвертация времени на сервере в CDM +/stats - Статистика """)} ''', parse_mode='HTML') @@ -161,7 +163,10 @@ def bal(message): id = user_in_db(API_TOKEN, tg=message.chat.id) coins = check_bal(API_TOKEN, id) nick = get_nick(API_TOKEN, id) + time = int(get_time(API_TOKEN, id)) + hours = time//3600 ; minutes = (time - hours*3600)//60 bot.reply_to(message, f'''Ваш баланс: {hcode(coins)} CDM +Время на сервере: {hcode(f"{hours}:{minutes}")} Ник: {hcode(nick)}''', parse_mode='HTML') @@ -196,6 +201,58 @@ def pay(message): else: bot.reply_to(message, '/pay ник количество') +@bot.message_handler(commands=['time2cdm']) +def time2cdm(message): + if checkauth(message): + id = user_in_db(API_TOKEN, tg=message.chat.id) + course = read('conf.json')['time2cdm'] + time = int(get_time(API_TOKEN, id)) + amount = time*course + if update_time(API_TOKEN, id, '0'): + if coins_add(API_TOKEN, id, str(amount)): + bot.reply_to(message, f'''Вы успешно конвертировали время на сервере в {hcode(str(amount))} CDM.''' +, parse_mode='HTML') + +@bot.message_handler(commands=['stats']) +def stats(message): + if checkauth(message): + data = get_stat(API_TOKEN) + bal = f'Баланс ({data["gbal_delta"]})' + t2cdm = f'Time2cdm ({data["time2cdm_delta"]})' + max_len = max(len(bal), len(t2cdm), 19) + bot.reply_to(message, f''' +```json +{bal.ljust(max_len)}: {data["gbal"]} +{t2cdm.ljust(max_len)}: {data["time2cdm"]} + +Среднее значение : {data["average"]} +Медиана : {data["median"]} +Минимум : {data["min"]} +Максимум : {data["max"]} + +Ввод/вывод алмазов : {data["up_diamond"]} +``` +''', parse_mode='Markdown') + +@bot.message_handler(commands=['course']) +def course(message): + conf = read('conf.json') + if message.from_user.id == conf['owner']: + bot.reply_to(message, f'''Текущий курс: `{conf['time2cdm']}` + +CDM в час: `{conf['time2cdm']*3600}`''', parse_mode = 'Markdown') + +@bot.message_handler(commands=['set_course']) +def set_course(message): + conf = read('conf.json') + if message.from_user.id == conf['owner']: + conf['time2cdm'] = float(message.text.split()[1]) + write(conf, 'conf.json') + bot.reply_to(message, f'''Установлен новый курс: `{conf['time2cdm']}` + +CDM в час: `{conf['time2cdm']*3600}`''', parse_mode = 'Markdown') + + @bot.message_handler(func=lambda message: True) def checks(message): if message.text == 'Баланс':