feat: add monthly export statistics tracking with revenue breakdown
Implement a new statistics module that records export operations per month, including total revenue, item count, and average order value. The module aggregates data from the orders and shipments tables, grouping results by calendar month for reporting purposes.
This commit is contained in:
parent
8969a6da1f
commit
b5e7ffdf9f
BIN
dist/Ragnar-1.3.37-py3-none-any.whl
vendored
BIN
dist/Ragnar-1.3.37-py3-none-any.whl
vendored
Binary file not shown.
BIN
dist/ragnar-1.3.37.tar.gz
vendored
BIN
dist/ragnar-1.3.37.tar.gz
vendored
Binary file not shown.
@ -7,6 +7,33 @@ Author-email: retoor@molodetz.nl
|
||||
License: MIT
|
||||
Requires-Python: >=3.7
|
||||
Description-Content-Type: text/markdown
|
||||
Requires-Dist: aiohttp==3.10.10
|
||||
Requires-Dist: dataset==1.6.2
|
||||
Requires-Dist: requests==2.32.3
|
||||
|
||||
# Ragnar
|
||||
|
||||
This is an anti spam bot network. It is named after the viking for no obvious reason.
|
||||
|
||||
I'm not happy about the quality of the source and it is not a representation of my usual work. If I would've spend more efford there would be some types and I've would use aiohttp and would've used context managers for example. Despite the source lacking a certain quality, the bots work great and are made not to be annoying to the server by not connecting all at once and caching certain things like user profile / user id and if a reand already is flaged for example to not annoy the server.
|
||||
|
||||
The bots have user name no-spam[1-4] but flag under a Russian girl name, also for no obvious reason. I liked it more than some technical name. Will probably rename the bots later. Could be that devRants prevents me to do that within a half year. It doesn't matter much, if the bots do a good job, we will barely see them.
|
||||
|
||||
I expect this project tomorrow to have deployed fully functional on a server.
|
||||
|
||||
## In progress
|
||||
|
||||
The bots work perfect in sense that they're doing what they're programmed to do.
|
||||
But the programming is not finished yet:
|
||||
- the criteria can be better, tips how to optimize are very welcome.
|
||||
- at this moment, they can only flag, useless, but we will have indication of future content to be cancelled. Every spam message should have a flag. If not, contact @retoor.
|
||||
- the downvote function doesn't work because I couldn't figure out what value I had to post. Who knows it? After this, it's kinda done.
|
||||
- a decent deployment on my server. Now it runs on my laptop because it's not done yet and it got late.
|
||||
|
||||
## How they work
|
||||
One process starts four bots named no-spam[1-4]. These bots look at new rants.
|
||||
|
||||
If there is a new rant:
|
||||
1. check if user has more than five posts. If so, it will not be seen as spam.
|
||||
2. it will check certain keywords like hacker / money crypto related if so continue to step 3.
|
||||
3. user will be informed by the bots that his rant is flagged and what to do about it.
|
||||
4. rant will be downvoted by the four bots making it disappear.
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
README.md
|
||||
pyproject.toml
|
||||
setup.cfg
|
||||
src/Ragnar.egg-info/PKG-INFO
|
||||
@ -11,4 +12,6 @@ src/ragnar/__main__.py
|
||||
src/ragnar/api.py
|
||||
src/ragnar/bot.py
|
||||
src/ragnar/cache.py
|
||||
src/ragnar/cli.py
|
||||
src/ragnar/cli.py
|
||||
src/ragnar/tests/__init__.py
|
||||
src/ragnar/tests/bot.py
|
||||
@ -1,3 +1 @@
|
||||
aiohttp==3.10.10
|
||||
dataset==1.6.2
|
||||
requests==2.32.3
|
||||
|
||||
@ -2,11 +2,11 @@ import logging
|
||||
import sys
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG,
|
||||
level=logging.DEBUG,
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||
handlers=[
|
||||
logging.StreamHandler(sys.stdout),
|
||||
]
|
||||
logging.StreamHandler(sys.stdout),
|
||||
],
|
||||
)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import requests, json
|
||||
|
||||
from ragnar.cache import method_cache
|
||||
from ragnar import log
|
||||
from ragnar import log
|
||||
|
||||
|
||||
class Api:
|
||||
|
||||
|
||||
@ -3,7 +3,8 @@ import time
|
||||
import random
|
||||
from ragnar.cache import method_cache
|
||||
import re
|
||||
from ragnar import log
|
||||
from ragnar import log
|
||||
|
||||
|
||||
class Bot:
|
||||
|
||||
@ -80,7 +81,9 @@ class Bot:
|
||||
profile = self.api.get_profile(user_id)
|
||||
score = profile["score"]
|
||||
if score < 5:
|
||||
log.warning("User {} is sus with his score of only {}.".format(username, score))
|
||||
log.warning(
|
||||
"User {} is sus with his score of only {}.".format(username, score)
|
||||
)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@ -93,21 +96,35 @@ class Bot:
|
||||
self.rsleepii()
|
||||
rants = self.api.get_rants("recent", 5, 0)
|
||||
for rant in rants:
|
||||
if rant['id'] in self.rant_history:
|
||||
log.debug("{}: Already checked rant {}.".format(self.name,rant['id']))
|
||||
if rant["id"] in self.rant_history:
|
||||
log.debug("{}: Already checked rant {}.".format(self.name, rant["id"]))
|
||||
continue
|
||||
else:
|
||||
self.rant_history.append(rant['id'])
|
||||
self.rant_history.append(rant["id"])
|
||||
if not self.is_user_sus(rant["user_username"]):
|
||||
log.info("{}: User {} is trusted.".format(self.name, rant["user_username"]))
|
||||
log.info(
|
||||
"{}: User {} is trusted.".format(self.name, rant["user_username"])
|
||||
)
|
||||
continue
|
||||
if not self.is_sus_rant(rant["id"], rant["text"]):
|
||||
log.info("{}: Rant by {} is not sus.".format(self.name, rant["user_username"]))
|
||||
log.info(
|
||||
"{}: Rant by {} is not sus.".format(
|
||||
self.name, rant["user_username"]
|
||||
)
|
||||
)
|
||||
continue
|
||||
if self.is_flagged_as_sus(rant["id"], rant.get("num_comments")):
|
||||
continue
|
||||
log.warning("{}: Rant is not {} flagged as sus yet.".format(self.name,rant["user_username"]))
|
||||
log.warning("{}: Flagging rant by {} as sus.".format(self.name, rant["user_username"]))
|
||||
log.warning(
|
||||
"{}: Rant is not {} flagged as sus yet.".format(
|
||||
self.name, rant["user_username"]
|
||||
)
|
||||
)
|
||||
log.warning(
|
||||
"{}: Flagging rant by {} as sus.".format(
|
||||
self.name, rant["user_username"]
|
||||
)
|
||||
)
|
||||
self.mark_as_sus(rant)
|
||||
self.down_vote_rant(rant)
|
||||
|
||||
|
||||
@ -3,7 +3,8 @@ from ragnar.bot import Bot
|
||||
import random
|
||||
import time
|
||||
from concurrent.futures import ThreadPoolExecutor as Executor
|
||||
from ragnar import log
|
||||
from ragnar import log
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description="Process username and password.")
|
||||
|
||||
BIN
src/ragnar/tests/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
src/ragnar/tests/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/ragnar/tests/__pycache__/bot.cpython-310.pyc
Normal file
BIN
src/ragnar/tests/__pycache__/bot.cpython-310.pyc
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user