Compare commits

..

No commits in common. 'master' and 'wownerod' have entirely different histories.

@ -15,11 +15,22 @@
"zao3w6isidntdbnyee5ufs7fyzmv7wzchpw32i3uo5eldjwmo4bxg2qd.onion:34568"
],
"clearnet": [
"spippolatori.it:34568",
"node2.monerodevs.org:34568",
"node3.monerodevs.org:34568",
"node.wowne.ro:34568",
"node.suchwow.xyz:34568"
"global.wownodes.com:34568",
"super.fast.node.xmr.pm:34568",
"node.wownero.club:34568",
"node.suchwow.xyz:34568",
"eu-west-1.wow.xmr.pm:34568",
"eu-west-2.wow.xmr.pm:34568",
"eu-west-3.wow.xmr.pm:34568",
"eu-west-4.wow.xmr.pm:34568",
"eu-west-5.wow.xmr.pm:34568",
"eu-west-6.wow.xmr.pm:34568",
"na-west-1.wow.xmr.pm:34568",
"much.wow.such.money:34568",
"very.wow.such.money:34568",
"169.119.33.174:34568",
"wow.bot.tips:34568",
"idontwanttogototoronto.wow.fail:34568"
]
},
"stagenet": {

@ -25,9 +25,6 @@ COIN_MODE = os.environ.get("WOWLET_COIN_MODE", "mainnet").lower()
TOR_SOCKS_PROXY = os.environ.get("WOWLET_TOR_SOCKS_PROXY", "socks5://127.0.0.1:9050")
RPC_WOWNERO_HOST = "127.0.0.1"
RPC_WOWNERO_PORT = 34568
# while fetching USD price from coingecko, also include these extra coins:
CRYPTO_RATES_COINS_EXTRA = {
"wownero": "wow"

@ -7,8 +7,6 @@ from typing import Union
from collections import Counter
from functools import partial
import aiohttp
import settings
from wowlet_backend.utils import httpget, popularity_contest
from wowlet_backend.tasks import WowletTask
@ -30,14 +28,134 @@ class BlockheightTask(WowletTask):
self._websocket_cmd = "blockheights"
self._fns = {
"xmr": {
"mainnet": [
self._blockchair,
partial(self._onion_explorer, url="https://xmrchain.net/"),
partial(self._onion_explorer, url="https://community.xmr.to/explorer/mainnet/"),
partial(self._onion_explorer, url="https://monero.exan.tech/")
],
"stagenet": [
partial(self._onion_explorer, url="https://stagenet.xmrchain.net/"),
partial(self._onion_explorer, url="https://community.xmr.to/explorer/stagenet/"),
partial(self._onion_explorer, url="https://monero-stagenet.exan.tech/")
]
},
"wow": {
"mainnet": [
partial(self._onion_explorer, url="https://explore.wownero.com/"),
]
},
"aeon": {
"mainnet": [
partial(self._onion_explorer, url="https://aeonblockexplorer.com/"),
],
"stagenet": [
partial(self._onion_explorer, url="http://162.210.173.151:8083/"),
]
},
"trtl": {
"mainnet": [
self._turtlenode,
self._turtlenetwork,
self._l33d4n
]
},
"xhv": {
"mainnet": [
partial(self._onion_explorer, url="https://explorer.havenprotocol.org/")
],
"stagenet": [
partial(self._onion_explorer, url="https://explorer.stagenet.havenprotocol.org/page/1")
]
},
"loki": {
"mainnet": [
partial(self._onion_explorer, url="https://lokiblocks.com/")
],
"testnet": [
partial(self._onion_explorer, url="https://lokitestnet.com/")
]
}
}
async def task(self) -> Union[dict, None]:
from wowlet_backend.factory import app
timeout = aiohttp.ClientTimeout(total=3)
coin_network_types = ["mainnet", "stagenet", "testnet"]
data = {t: 0 for t in coin_network_types}
for coin_network_type in coin_network_types:
if coin_network_type not in self._fns[settings.COIN_SYMBOL]:
continue
heights = []
for fn in self._fns[settings.COIN_SYMBOL][coin_network_type]:
fn_name = fn.func.__name__ if isinstance(fn, partial) else fn.__name__
try:
result = await fn()
heights.append(result)
except Exception as ex:
app.logger.error(f"blockheight fetch failed from {fn_name}(): {ex}")
continue
if heights:
data[coin_network_type] = popularity_contest(heights)
if data["mainnet"] == 0: # only care about mainnet
app.logger.error(f"Failed to parse latest blockheight!")
return
return data
async def _blockchair(self) -> int:
re_blockheight = r"<a href=\".*\">(\d+)</a>"
url = "https://blockchair.com/monero"
content = await httpget(url, json=False, raise_for_status=True)
height = re.findall(re_blockheight, content)
height = max(map(int, height))
return height
async def _wownero(self) -> int:
url = "https://explore.wownero.com/"
return await BlockheightTask._onion_explorer(url)
async def _turtlenode(self) -> int:
url = "https://public.turtlenode.net/info"
blob = await httpget(url, json=True, raise_for_status=True)
height = int(blob.get("height", 0))
if height <= 0:
raise Exception("bad height")
return height
async def _turtlenetwork(self) -> int:
url = "https://tnnode2.turtlenetwork.eu/blocks/height"
blob = await httpget(url, json=True, raise_for_status=True)
height = int(blob.get("height", 0))
if height <= 0:
raise Exception("bad height")
return height
async def _l33d4n(self):
url = "https://blockapi.turtlepay.io/block/header/top"
blob = await httpget(url, json=True, raise_for_status=True)
height = int(blob.get("height", 0))
if height <= 0:
raise Exception("bad height")
return height
async with aiohttp.ClientSession(timeout=timeout) as session:
async with session.get(f'http://{settings.RPC_WOWNERO_HOST}:{settings.RPC_WOWNERO_PORT}/get_height') as resp:
blob = await resp.json()
@staticmethod
async def _onion_explorer(url):
"""
Pages that are based on:
https://github.com/moneroexamples/onion-monero-blockchain-explorer
"""
re_blockheight = r"block\/(\d+)\"\>"
content = await httpget(url, json=False)
return {
'mainnet': blob['height']
}
height = re.findall(re_blockheight, content)
height = max(map(int, height))
return height

@ -29,4 +29,26 @@ class ForumThreadsTask(WowletTask):
from wowlet_backend.factory import app
blob = await httpget(self._http_endpoint, json=True)
return blob
users = {z['id']: z for z in blob["users"]}
topics = []
for topic in blob['topic_list']['topics']:
if topic.get("pinned_globally", True):
continue
try:
u = next(z for z in topic["posters"] if "original poster" in z['description'].lower())['user_id']
href = f"https://forum.wownero.com/t/{topic['slug']}"
topics.append({
"id": topic["id"],
"title": topic["title"],
"comments": topic["posts_count"] - 1,
"created_at": parse(topic["created_at"]).strftime("%Y-%m-%d %H:%M"),
"author": users[u]['username'],
"permalink": href
})
except Exception as ex:
app.logger.error(f"skipping a forum topic; {ex}")
return topics[:25]

@ -9,7 +9,6 @@ from typing import List, Union
from datetime import datetime
import aiofiles
from quart import current_app as app
import settings
from wowlet_backend.utils import httpget
@ -94,15 +93,6 @@ class HistoricalPriceTask(WowletTask):
data filtered by the parameters."""
from wowlet_backend.factory import cache
# redis keys are always strings, convert input parameters
year = str(year)
if isinstance(month, int):
month = str(month)
if not year.isnumeric() or (month and not month.isnumeric()):
app.logger.error(f"get() called with year: {year}, month {month}, not a number")
return
blob = await cache.get("historical_fiat")
blob = json.loads(blob)
if year not in blob:
@ -112,13 +102,13 @@ class HistoricalPriceTask(WowletTask):
if not month:
for _m, days in blob[year].items():
for day, price in days.items():
rtn[datetime(int(year), int(_m), int(day)).strftime('%Y%m%d')] = price
rtn[datetime(year, _m, day).strftime('%Y%m%d')] = price
return rtn
if month not in blob[year]:
return
for day, price in blob[year][month].items():
rtn[datetime(int(year), int(month), int(day)).strftime('%Y%m%d')] = price
rtn[datetime(year, month, day).strftime('%Y%m%d')] = price
return rtn

@ -2,7 +2,7 @@
# Copyright (c) 2020, The Monero Project.
# Copyright (c) 2020, dsc@xmr.pm
import json, asyncio
import json
from typing import List, Union
import settings
@ -12,7 +12,7 @@ from wowlet_backend.factory import cache
class CryptoRatesTask(WowletTask):
def __init__(self, interval: int = 600):
def __init__(self, interval: int = 180):
super(CryptoRatesTask, self).__init__(interval)
self._cache_key = "crypto_rates"
@ -90,5 +90,4 @@ class CryptoRatesTask(WowletTask):
pass
rates.append(obj)
await asyncio.sleep(10)
return rates

@ -2,7 +2,6 @@
# Copyright (c) 2022, The Monero Project.
# Copyright (c) 2022, dsc@xmr.pm
from typing import List
from dateutil.parser import parse
import settings
@ -22,7 +21,7 @@ class YellWowTask(WowletTask):
self._http_endpoint = "https://yellow.wownero.com/api/user/"
async def task(self) -> List[dict]:
async def task(self) -> list[dict]:
blob = await httpget(self._http_endpoint)
if not isinstance(blob, list) or not blob:
raise Exception(f"Invalid JSON response for {self._http_endpoint}")

@ -83,8 +83,7 @@ async def wowlet_data():
"suchwow",
"forum",
"wowlet_releases",
"yellwow",
"wownerod_releases"
"yellwow"
]
data = {keys[i]: json.loads(val) if val else None for i, val in enumerate(await cache.mget(*keys))}

Loading…
Cancel
Save