dysnomia-chat-log/main.py

139 lines
5.5 KiB
Python

import asyncio
import json
import re
import sys
import time
import warnings
from datetime import datetime, timezone
from json import JSONDecodeError
from web3 import Web3
from web3.exceptions import BlockNotFound
from web3_multi_provider import FallbackProvider
from common import *
from logs import *
warnings.filterwarnings("ignore")
web3 = Web3(FallbackProvider(json.loads(os.getenv('RPC_SERVER'))))
log_contract = web3.eth.contract(
os.getenv('LOG_CONTRACT_ADDRESS'),
abi=json.load(open("./data/abi/{}".format(os.getenv('LOG_CONTRACT_ABI_FILE'))))
)
block_cache = {}
async def keep_chat_updated(event_filter, poll_interval):
while True:
for event in event_filter.get_new_entries():
output_line(event)
await asyncio.sleep(poll_interval)
def preload_chat(earliest_block, latest_block):
event_logs = web3.eth.get_logs({
"fromBlock": int(earliest_block),
"toBlock": int(latest_block),
"topics": [os.getenv('LOG_TOPIC')],
"address": os.getenv('LOG_CONTRACT_ADDRESS')
})
for log in event_logs:
output_line(log)
def load_chat(latest_block):
event_filter = web3.eth.filter({
"fromBlock": int(latest_block),
"topics": [os.getenv('LOG_TOPIC')],
"address": os.getenv('LOG_CONTRACT_ADDRESS')
})
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
asyncio.run(keep_chat_updated(event_filter, 2))
def output_line(event):
try:
tx_receipt = web3.eth.get_transaction_receipt(event.transactionHash)
decoded_data = log_contract.events.LogEvent().process_receipt(tx_receipt)
except Exception as e:
logging.error(e)
return
if decoded_data[0]['args']['Aura'] and decoded_data[0]['args']['Soul']:
# get the block and save it to cache
block_number = tx_receipt['blockNumber']
if block_number not in block_cache:
attempts = 3
block_cache[block_number] = None
while attempts > 0:
try:
block_cache[block_number] = web3.eth.get_block(block_number)
except BlockNotFound:
attempts = attempts - 1
time.sleep(3)
continue
else:
break
if not block_cache[block_number]:
raise Exception("Could not get block {}".format(block_number))
# log the message and output to console
timestamp = datetime.fromtimestamp(block_cache[block_number]['timestamp'], tz=timezone.utc)
message = "{}:{} {}".format(decoded_data[0]['args']['Aura'], decoded_data[0]['args']['Soul'], decoded_data[0]['args']['LogLine'])
log_message(os.getenv('CHANNEL_NAME'), "[{}] {}".format(timestamp.strftime("%Y-%m-%d %H:%M:%S"), message))
print("[{}] {}".format(timestamp.strftime("%Y-%m-%d %H:%M:%S"), message if os.getenv('SHOW_AURA_AND_SOUL') != '0' else decoded_data[0]['args']['LogLine']))
# save latest block number
room = json.load(open(room_file := "{}/rooms/{}.json".format(os.getenv('DATA_FOLDER'), os.getenv('CHANNEL_NAME')), 'r'))
room['last_block'] = tx_receipt['blockNumber']
open(room_file, 'w').write(json.dumps(room))
if __name__ == '__main__':
while True:
try:
os.system('cls' if os.name == 'nt' else 'clear')
# create the log and rooms folder if it doesn't exist
os.makedirs("{}/logs/".format(os.getenv('DATA_FOLDER')), exist_ok=True)
os.makedirs("{}/rooms/".format(os.getenv('DATA_FOLDER')), exist_ok=True)
# create the rooms file if it doesn't exist
try:
room = json.load(open(room_file := "{}/rooms/{}.json".format(os.getenv('DATA_FOLDER'), os.getenv('CHANNEL_NAME')), 'r')) # TODO: change this to target an address
except (JSONDecodeError, FileNotFoundError):
room = {
"label": os.getenv('CHANNEL_NAME'),
"last_block": 0,
"preloaded": False,
}
open(room_file, 'w').write(json.dumps(room))
log_file = "{}/logs/{}.log".format(os.getenv('DATA_FOLDER'), "VOID")
# grab the entire log if the log file doesn't exist
latest_block = web3.eth.get_block('latest')
if not room['preloaded']:
if os.path.exists(log_file):
os.remove(log_file)
block_cache[latest_block.number] = latest_block
start_block_number = os.getenv('START_BLOCK')
preload_chat(start_block_number, latest_block.number)
room['preloaded'] = True
else:
# print past log to console
logs = read_file_to_list(log_file)
for i, log in enumerate(logs):
if os.getenv('SHOW_AURA_AND_SOUL') != '0':
print(log)
else:
match = re.match(r'^.*( [\d]+:[\d]+) .*$', log)
if match:
print(log.replace(match.group(1), ''))
preload_chat(room['last_block'], latest_block.number)
room['last_block'] = latest_block.number
open(room_file, 'w').write(json.dumps(room))
# check for new messages
load_chat(room['last_block'])
except KeyboardInterrupt:
break
except Exception as e:
time.sleep(3)
logging.error(e)