2022-11-15 09:25:04 +00:00
|
|
|
from gql import gql, Client
|
|
|
|
from gql.transport.aiohttp import AIOHTTPTransport
|
|
|
|
import asyncio
|
2022-11-15 12:04:22 +00:00
|
|
|
import json
|
|
|
|
from base.redis import redis
|
2022-11-15 09:25:04 +00:00
|
|
|
from services.zine.topics import TopicStorage
|
|
|
|
|
|
|
|
query_ackee_views = gql(
|
|
|
|
"""
|
|
|
|
query getDomainsFacts {
|
|
|
|
domains {
|
|
|
|
statistics {
|
|
|
|
views {
|
|
|
|
id
|
|
|
|
count
|
|
|
|
}
|
|
|
|
pages {
|
|
|
|
id
|
|
|
|
count
|
|
|
|
created
|
|
|
|
}
|
|
|
|
}
|
|
|
|
facts {
|
|
|
|
activeVisitors
|
|
|
|
# averageViews
|
|
|
|
# averageDuration
|
|
|
|
viewsToday
|
|
|
|
viewsMonth
|
|
|
|
viewsYear
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2022-11-15 12:04:22 +00:00
|
|
|
class ViewStat:
|
2022-11-15 09:25:04 +00:00
|
|
|
lock = asyncio.Lock()
|
|
|
|
by_slugs = {}
|
|
|
|
by_topics = {}
|
|
|
|
period = 30 * 60 # 30 minutes
|
|
|
|
transport = AIOHTTPTransport(url="https://ackee.discours.io/")
|
|
|
|
client = Client(transport=transport, fetch_schema_from_transport=True)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
async def load_views():
|
|
|
|
# TODO: when the struture of paylod will be transparent
|
|
|
|
# TODO: perhaps ackee token getting here
|
|
|
|
|
2022-11-15 12:04:22 +00:00
|
|
|
self = ViewStat
|
2022-11-15 09:25:04 +00:00
|
|
|
async with self.lock:
|
2022-11-15 12:04:22 +00:00
|
|
|
self.by_topics = await redis.execute("GET", "views_by_topics")
|
|
|
|
if self.by_topics:
|
|
|
|
self.by_topics = json.loads(self.by_topics)
|
|
|
|
self.by_slugs = await redis.execute("GET", "views_by_shouts")
|
|
|
|
if self.by_slugs:
|
|
|
|
self.by_slugs = json.loads(self.by_slugs)
|
|
|
|
|
|
|
|
domains = await self.client.execute_async(query_ackee_views)
|
2022-11-15 09:25:04 +00:00
|
|
|
print("[stat.ackee] loaded domains")
|
|
|
|
print(domains)
|
|
|
|
|
|
|
|
print('\n\n# TODO: something here...\n\n')
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
async def get_shout(shout_slug):
|
2022-11-15 12:04:22 +00:00
|
|
|
self = ViewStat
|
2022-11-15 09:25:04 +00:00
|
|
|
async with self.lock:
|
|
|
|
return self.by_slugs.get(shout_slug) or 0
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
async def get_topic(topic_slug):
|
2022-11-15 12:04:22 +00:00
|
|
|
self = ViewStat
|
2022-11-15 09:25:04 +00:00
|
|
|
async with self.lock:
|
|
|
|
shouts = self.by_topics.get(topic_slug)
|
|
|
|
topic_views = 0
|
|
|
|
for v in shouts.values():
|
|
|
|
topic_views += v
|
|
|
|
return topic_views
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
async def increment(shout_slug, amount=1):
|
2022-11-15 12:04:22 +00:00
|
|
|
self = ViewStat
|
2022-11-15 09:25:04 +00:00
|
|
|
async with self.lock:
|
|
|
|
self.by_slugs[shout_slug] = self.by_slugs.get(shout_slug) or 0
|
|
|
|
self.by_slugs[shout_slug] += amount
|
2022-11-15 12:04:22 +00:00
|
|
|
await redis.execute(
|
|
|
|
"SET",
|
|
|
|
f"views_by_shouts/{shout_slug}",
|
|
|
|
str(self.by_slugs[shout_slug])
|
|
|
|
)
|
2022-11-15 09:25:04 +00:00
|
|
|
shout_topics = await TopicStorage.get_topics_by_slugs([shout_slug, ])
|
|
|
|
for t in shout_topics:
|
|
|
|
self.by_topics[t] = self.by_topics.get(t) or {}
|
|
|
|
self.by_topics[t][shout_slug] = self.by_topics[t].get(shout_slug) or 0
|
|
|
|
self.by_topics[t][shout_slug] += amount
|
2022-11-15 12:04:22 +00:00
|
|
|
await redis.execute(
|
|
|
|
"SET",
|
|
|
|
f"views_by_topics/{t}/{shout_slug}",
|
|
|
|
str(self.by_topics[t][shout_slug])
|
|
|
|
)
|
2022-11-15 09:25:04 +00:00
|
|
|
|
|
|
|
@staticmethod
|
2022-11-15 12:04:22 +00:00
|
|
|
async def reset():
|
|
|
|
self = ViewStat
|
|
|
|
self.by_topics = {}
|
|
|
|
self.by_slugs = {}
|
2022-11-15 09:25:04 +00:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
async def worker():
|
2022-11-15 12:04:22 +00:00
|
|
|
self = ViewStat
|
2022-11-15 09:25:04 +00:00
|
|
|
while True:
|
|
|
|
try:
|
2022-11-15 12:04:22 +00:00
|
|
|
await self.load_views()
|
2022-11-15 09:25:04 +00:00
|
|
|
except Exception as err:
|
|
|
|
print("[stat.ackee] : %s" % (err))
|
2022-11-15 12:04:22 +00:00
|
|
|
print("[stat.ackee] renew period: %d minutes" % (ViewStat.period / 60))
|
|
|
|
await asyncio.sleep(self.period)
|