mirror of
https://github.com/fotoente/MiCECo.git
synced 2024-10-22 23:19:09 +00:00
Added following functionalities
- Emojis can be ignored - If note length is higher than max length only the first five emojis/reactions will be printed - It is possible to change how the note is presented.
This commit is contained in:
parent
9402ce3c28
commit
d506ea627d
6 changed files with 159 additions and 46 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
emojicount.cfg
|
emojicount.cfg
|
||||||
miceco.cfg
|
miceco.cfg
|
||||||
|
roboduck.cfg
|
||||||
|
|
19
README.md
19
README.md
|
@ -13,7 +13,8 @@ Edit the file `example-miceco.cfg` (see table below) and save it as `miceco.cfg`
|
||||||
Install following Python packages via `pip install`
|
Install following Python packages via `pip install`
|
||||||
```
|
```
|
||||||
emoji
|
emoji
|
||||||
python-dateutil
|
configparser
|
||||||
|
requests
|
||||||
```
|
```
|
||||||
|
|
||||||
or use `pip install -r requirements.txt` in the cloned folder
|
or use `pip install -r requirements.txt` in the cloned folder
|
||||||
|
@ -25,17 +26,27 @@ In your console type `crontab -e`
|
||||||
Add `0 9 * * * python3 /path/to/file/miceco.py > /path/to/file/miceco_output.txt`
|
Add `0 9 * * * python3 /path/to/file/miceco.py > /path/to/file/miceco_output.txt`
|
||||||
The script will now be run every day on 9:00am server time.
|
The script will now be run every day on 9:00am server time.
|
||||||
|
|
||||||
|
### Available flags
|
||||||
|
There are two flags that can be used to specify which external files the script gonna use
|
||||||
|
|
||||||
|
| Flag | Long name | controlled behaviour |
|
||||||
|
|------|-------------|------------------------------------------------------------------------------------------|
|
||||||
|
| `-c` | `--config` | What configuration file should be used.<br/>Without this flag `miceco.cfg` will be used. |
|
||||||
|
| `-i` | `--ignored` | Which emojis should be ignored.<br/> Without this `ignoredemojis.txt` will be used |
|
||||||
|
|
||||||
### Options for the config file
|
### Options for the config file
|
||||||
| Name | Values | Explanation |
|
| Name | Values | Explanation |
|
||||||
|----|----|----|
|
|----------------|------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|instance|domain.tld|The domain name for your Misskey instance that you want to read the notes from. Only supply the domain name and TLD, no `/`,`:` or `https`
|
| instance | domain.tld | The domain name for your Misskey instance that you want to read the notes from. Only supply the domain name and TLD, no `/`,`:` or `https` |
|
||||||
| user | `username` | The user you want to read the notes from |
|
| user | `username` | The user you want to read the notes from |
|
||||||
| token | `String` | The token for your bot. Needs permission to write notes |
|
| token | `String` | The token for your bot. Needs permission to write notes |
|
||||||
| getReaction | `Boolean` | Should reactions emojis be counted as well? `True` or `False` |
|
| getReaction | `Boolean` | Should reactions emojis be counted as well? `True` or `False` |
|
||||||
|
| ignoreEmojis | `Boolean` | Should Emojis that are specified in `ignoredemojis.txt` be ignored? `True`or `False` | |
|
||||||
|
| noteVisibility | `String` | How should the note be shown in the Timeline? `public`: Visible for everyone<br/>`folowers`: only visible for your followers<br/>`specified`: Only you can see it |
|
||||||
|
|
||||||
### Other notes
|
### Other notes
|
||||||
The script is written in a way that only the notes and reactions from yesterday(!!!) are caught and counted. There is no option currently to specify the date range for collection.
|
The script is written in a way that only the notes and reactions from yesterday(!!!) are caught and counted. There is no option currently to specify the date range for collection.
|
||||||
|
|
||||||
The exact timestamp to get yesterday is determined by the timezone of your server. At the moment there is no way to change the timezone.
|
The exact timestamp to get yesterday is determined by the timezone of your server. At the moment there is no way to change the timezone.
|
||||||
|
|
||||||
#### Feel free to open a feature request or issue if you want something changed!
|
If the note is longer than the maximum note length of the instance, then only the five most used emojis (and five most used reactions) will be shown.
|
||||||
|
|
|
@ -3,3 +3,5 @@ instance=//DOMAIN.TLD//
|
||||||
user=//USERNAME//
|
user=//USERNAME//
|
||||||
token=//TOKEN HERE//
|
token=//TOKEN HERE//
|
||||||
getReaction=True
|
getReaction=True
|
||||||
|
ignoreEmojis=true
|
||||||
|
noteVisibility=public
|
15
ignoredemojis.txt
Normal file
15
ignoredemojis.txt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
🟩
|
||||||
|
⬜
|
||||||
|
🟨
|
||||||
|
🟪
|
||||||
|
⚔
|
||||||
|
👹
|
||||||
|
🪄
|
||||||
|
🪙
|
||||||
|
🔸
|
||||||
|
🎉
|
||||||
|
🇩🇪
|
||||||
|
↗
|
||||||
|
⬇
|
||||||
|
↙️
|
||||||
|
➡️
|
149
miceco.py
149
miceco.py
|
@ -2,11 +2,11 @@ import configparser
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import argparse
|
||||||
from datetime import *
|
from datetime import *
|
||||||
# import dateutil.relativedelta
|
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import emoji as emojilib
|
import emoji as emojilib
|
||||||
|
# TODO: Replace with emojis library!
|
||||||
|
|
||||||
|
|
||||||
def check_str_to_bool(input_text) -> bool:
|
def check_str_to_bool(input_text) -> bool:
|
||||||
|
@ -27,7 +27,15 @@ doubleList = []
|
||||||
text = ""
|
text = ""
|
||||||
getReactions = False
|
getReactions = False
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("-c", "--config", help="location of the configuration file")
|
||||||
|
parser.add_argument("-i", "--ignored", help="location of the file which emojis are ignored while counting")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.config is None:
|
||||||
configfilePath = os.path.join(os.path.dirname(__file__), 'miceco.cfg')
|
configfilePath = os.path.join(os.path.dirname(__file__), 'miceco.cfg')
|
||||||
|
else:
|
||||||
|
configfilePath = args.config
|
||||||
|
|
||||||
if not os.path.exists(configfilePath):
|
if not os.path.exists(configfilePath):
|
||||||
print("No config File found!")
|
print("No config File found!")
|
||||||
|
@ -47,6 +55,33 @@ try:
|
||||||
except (TypeError, ValueError) as err:
|
except (TypeError, ValueError) as err:
|
||||||
getReactions = False
|
getReactions = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
ignoreEmojis = check_str_to_bool(config.get("misskey", "ignoreEmojis"))
|
||||||
|
except (TypeError, ValueError) as err:
|
||||||
|
ignoreEmojis = False
|
||||||
|
|
||||||
|
if ignoreEmojis:
|
||||||
|
if args.ignored is None:
|
||||||
|
ignored_path = os.path.join(os.path.dirname(__file__), "ignoredemojis.txt")
|
||||||
|
else:
|
||||||
|
ignored_path = args.ignored
|
||||||
|
|
||||||
|
if not os.path.exists(ignored_path):
|
||||||
|
print("No file for ignored emojis found!")
|
||||||
|
print("Setting skipped!")
|
||||||
|
|
||||||
|
if os.path.exists(ignored_path):
|
||||||
|
with open(ignored_path, "r", encoding="utf8") as ignored_file:
|
||||||
|
ignored_emojis = []
|
||||||
|
for element in ignored_file.readlines():
|
||||||
|
i = element.strip()
|
||||||
|
ignored_emojis.append(emojilib.demojize(i))
|
||||||
|
|
||||||
|
noteVisibility = config.get("misskey", "noteVisibility") # How should the note be printed?
|
||||||
|
if noteVisibility != "public" and noteVisibility != "home" and noteVisibility != "followers" and noteVisibility != \
|
||||||
|
"specified":
|
||||||
|
noteVisibility = "followers"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
req = requests.post(url + "/users/show", json={"username": user, "host": None, "i": token})
|
req = requests.post(url + "/users/show", json={"username": user, "host": None, "i": token})
|
||||||
req.raise_for_status()
|
req.raise_for_status()
|
||||||
|
@ -55,12 +90,24 @@ except requests.exceptions.HTTPError as err:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
userid = req.json()["id"]
|
userid = req.json()["id"]
|
||||||
|
if req.json()["name"] is not None: # If no nickname is set, just user the username instead
|
||||||
nickname = req.json()["name"]
|
nickname = req.json()["name"]
|
||||||
|
else:
|
||||||
|
nickname = req.json()["username"]
|
||||||
|
|
||||||
|
# Get max note length
|
||||||
|
try:
|
||||||
|
req = requests.post(url + "/meta", json={"detail": True, "i": token})
|
||||||
|
req.raise_for_status()
|
||||||
|
except requests.exceptions.HTTPError as err:
|
||||||
|
print("Couldn't get maximal note length!\n" + str(err))
|
||||||
|
print("Setting max note length to 3.000 characters")
|
||||||
|
max_note_length = 3000
|
||||||
|
|
||||||
|
max_note_length = int(req.json()["maxNoteTextLength"])
|
||||||
|
|
||||||
today = date.today()
|
today = date.today()
|
||||||
formerDate = today - timedelta(days=1)
|
formerDate = today - timedelta(days=1)
|
||||||
# formerDate = today - timedelta(weeks=1) #Last week
|
|
||||||
# formerDate = today - dateutil.relativedelta.relativedelta(months=1)
|
|
||||||
formerDateMidnight = datetime.combine(formerDate, time(0, 0, 0))
|
formerDateMidnight = datetime.combine(formerDate, time(0, 0, 0))
|
||||||
todayMidnight = datetime.combine(today, time(0, 0, 0))
|
todayMidnight = datetime.combine(today, time(0, 0, 0))
|
||||||
|
|
||||||
|
@ -93,12 +140,11 @@ while True:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
for jsonObj in req.json():
|
for jsonObj in req.json():
|
||||||
# textDict = jsonObj
|
|
||||||
noteList.append(jsonObj)
|
noteList.append(jsonObj)
|
||||||
|
|
||||||
formerTimestamp = lastTimestamp
|
formerTimestamp = lastTimestamp
|
||||||
|
|
||||||
if not len(noteList) <= 1: # If there is one or less notes, then break the while loop
|
if not len(noteList) <= 0: # If there is zero notes, then break the while loop
|
||||||
lastTime = noteList[len(noteList) - 1]["createdAt"]
|
lastTime = noteList[len(noteList) - 1]["createdAt"]
|
||||||
lastTimestamp = int(datetime.timestamp(datetime.strptime(lastTime, '%Y-%m-%dT%H:%M:%S.%f%z')) * 1000)
|
lastTimestamp = int(datetime.timestamp(datetime.strptime(lastTime, '%Y-%m-%dT%H:%M:%S.%f%z')) * 1000)
|
||||||
else:
|
else:
|
||||||
|
@ -119,17 +165,17 @@ for element in noteList:
|
||||||
|
|
||||||
if emojis is not None:
|
if emojis is not None:
|
||||||
for emoji in emojis:
|
for emoji in emojis:
|
||||||
if emoji["name"].find(
|
if emoji["name"].find("@") == -1: # Only emojis from the own instance, because reactions will be in
|
||||||
"@") == -1: # Only emojis from the own instance, because reactions will be in "emojis"
|
# "emojis" too
|
||||||
# too
|
emojiname = ":" + emoji["name"] + ":"
|
||||||
if not emoji["name"] in doubleList:
|
if emojiname not in doubleList:
|
||||||
doubleList.append(emoji["name"]) # Easy way to prevent a double emoji in the list.
|
doubleList.append(emojiname) # Easy way to prevent a double emoji in the list.
|
||||||
emojiDict = {"emoji": ":" + emoji["name"] + ":", "count": 0}
|
emojiDict = {"emoji": emojiname, "count": 0}
|
||||||
emojiList.append(emojiDict)
|
emojiList.append(emojiDict)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
index = doubleList.index(emoji["name"])
|
index = doubleList.index(":" + emoji["name"] + ":")
|
||||||
|
|
||||||
emojiList[index]["count"] += element["text"].count(emojiList[index]["emoji"])
|
emojiList[index]["count"] += element["text"].count(emojiList[index]["emoji"])
|
||||||
|
|
||||||
|
@ -142,19 +188,29 @@ for element in noteList:
|
||||||
UTF8text = element["text"] + " " + element["cw"]
|
UTF8text = element["text"] + " " + element["cw"]
|
||||||
else:
|
else:
|
||||||
UTF8text = element["text"]
|
UTF8text = element["text"]
|
||||||
UTF8List = re.findall(emojilib.get_emoji_regexp(), UTF8text) # Find all UTF8 Emojis in Text and CW text
|
UTF8ListRaw = re.findall(emojilib.get_emoji_regexp(), UTF8text) # Find all UTF8 Emojis in Text and CW text
|
||||||
|
UTF8text = emojilib.demojize(UTF8text)
|
||||||
if len(UTF8List) > 0:
|
# TODO urgent! replace "get_emoji_regexp"
|
||||||
UTF8List = list(set(UTF8List))
|
if len(UTF8ListRaw) > 0:
|
||||||
|
UTF8List = list(set(UTF8ListRaw))
|
||||||
for emoji in UTF8List:
|
for emoji in UTF8List:
|
||||||
|
emoji = emojilib.demojize(emoji)
|
||||||
if emoji not in doubleList:
|
if emoji not in doubleList:
|
||||||
doubleList.append(emoji) # Easy way to prevent a double emoji in the list.
|
doubleList.append(emoji) # Easy way to prevent a double emoji in the list without checking the whole
|
||||||
|
# dictionary
|
||||||
emojiDict = {"emoji": emoji, "count": 0}
|
emojiDict = {"emoji": emoji, "count": 0}
|
||||||
emojiList.append(emojiDict)
|
emojiList.append(emojiDict)
|
||||||
|
|
||||||
index = doubleList.index(emoji)
|
index = doubleList.index(emoji)
|
||||||
emojiList[index]["count"] += UTF8text.count(emoji)
|
emojiList[index]["count"] += UTF8text.count(emoji)
|
||||||
|
|
||||||
|
if ignoreEmojis:
|
||||||
|
for ignoredEmoji in ignored_emojis:
|
||||||
|
if ignoredEmoji in doubleList:
|
||||||
|
indx = doubleList.index(ignoredEmoji)
|
||||||
|
del doubleList[indx]
|
||||||
|
del emojiList[indx]
|
||||||
|
|
||||||
doubleList = []
|
doubleList = []
|
||||||
emojiList = sorted(emojiList, reverse=True, key=lambda d: d["count"]) # Sort it by the most used Emojis!
|
emojiList = sorted(emojiList, reverse=True, key=lambda d: d["count"]) # Sort it by the most used Emojis!
|
||||||
|
|
||||||
|
@ -185,7 +241,7 @@ if getReactions:
|
||||||
reactionList.append(jsonObj)
|
reactionList.append(jsonObj)
|
||||||
|
|
||||||
formerTimestamp = lastTimestamp
|
formerTimestamp = lastTimestamp
|
||||||
if not len(reactionList) <=1:
|
if not len(reactionList) <= 0:
|
||||||
lastTime = reactionList[len(reactionList) - 1]["createdAt"]
|
lastTime = reactionList[len(reactionList) - 1]["createdAt"]
|
||||||
lastTimestamp = int(datetime.timestamp(datetime.strptime(lastTime, '%Y-%m-%dT%H:%M:%S.%f%z')) * 1000)
|
lastTimestamp = int(datetime.timestamp(datetime.strptime(lastTime, '%Y-%m-%dT%H:%M:%S.%f%z')) * 1000)
|
||||||
else:
|
else:
|
||||||
|
@ -205,7 +261,6 @@ if getReactions:
|
||||||
reactList.append(emojiDict)
|
reactList.append(emojiDict)
|
||||||
|
|
||||||
index = doubleList.index(react)
|
index = doubleList.index(react)
|
||||||
|
|
||||||
reactList[index]["count"] += 1
|
reactList[index]["count"] += 1
|
||||||
|
|
||||||
doubleList = []
|
doubleList = []
|
||||||
|
@ -215,10 +270,13 @@ if getReactions:
|
||||||
for react in reactList: # Summarize the number of Reactions used
|
for react in reactList: # Summarize the number of Reactions used
|
||||||
reactionCount += react["count"]
|
reactionCount += react["count"]
|
||||||
|
|
||||||
reactText = "\n\n\nAnd used " + str(reactionCount) + " reactions:\n\n" + chr(9553) + " "
|
initial_react_text = "\n\n\nAnd used " + str(reactionCount) + " reactions:\n\n" + chr(9553) + " "
|
||||||
|
reactText = initial_react_text
|
||||||
|
|
||||||
for reactionElement in reactList:
|
for reactionElement in reactList:
|
||||||
reactText += str(reactionElement["count"]) + "x " + reactionElement["reaction"] + " " + chr(9553) + " "
|
count = reactionElement["count"]
|
||||||
|
reaction = reactionElement["reaction"]
|
||||||
|
reactText += f"{count}x {reaction} " + chr(9553) + " "
|
||||||
else:
|
else:
|
||||||
reactText = "\n\nAnd didn't use any reactions."
|
reactText = "\n\nAnd didn't use any reactions."
|
||||||
else:
|
else:
|
||||||
|
@ -228,25 +286,50 @@ for count in emojiList:
|
||||||
emojisTotal += count["count"]
|
emojisTotal += count["count"]
|
||||||
|
|
||||||
if emojisTotal > 0:
|
if emojisTotal > 0:
|
||||||
text = nickname + " has written " + str(len(noteList)) + " Notes yesterday, " + formerDate.strftime(
|
initial_text = nickname + " has written " + str(len(noteList)) + " Notes yesterday, " + formerDate.strftime(
|
||||||
'%a %d-%m-%Y') + "\nand used a total of " + str(emojisTotal) + " Emojis. #miceco" + chr(8203) + chr(8203) + chr(
|
'%a %d-%m-%Y') + "\nand used a total of " + str(emojisTotal) + " Emojis. #miceco" + chr(8203) + chr(8203) + chr(
|
||||||
8203) + "\n\n" + chr(
|
8203) + "\n\n" + chr(9553) + " "
|
||||||
9553) + " "
|
text = initial_text
|
||||||
for element in emojiList:
|
emoji_text = ""
|
||||||
text += str(element["count"]) + "x\u00A0" + element["emoji"] + " " + chr(9553) + " "
|
|
||||||
else:
|
|
||||||
text = nickname + " has written " + str(len(noteList)) + " Notes yesterday, " + formerDate.strftime(
|
|
||||||
'%a %d-%m-%Y') + "\nand didn't used any emojis. #miceco" + chr(8203) + chr(8203) + chr(
|
|
||||||
8203)
|
|
||||||
|
|
||||||
text += reactText
|
for element in emojiList:
|
||||||
|
count = element["count"]
|
||||||
|
emoji = element["emoji"]
|
||||||
|
emoji_text += f"{count}x {emoji} " + chr(9553) + " "
|
||||||
|
|
||||||
|
else:
|
||||||
|
emoji_text = nickname + " has written " + str(len(noteList)) + " Notes yesterday, " + formerDate.strftime(
|
||||||
|
'%a %d-%m-%Y') + "\nand didn't used any emojis. #miceco" + chr(8203) + chr(8203) + chr(8203)
|
||||||
|
|
||||||
|
text += emoji_text + reactText
|
||||||
|
text = emojilib.emojize(text)
|
||||||
|
# print(text)
|
||||||
|
|
||||||
|
if max_note_length < len(text):
|
||||||
|
emoji_text = initial_text
|
||||||
|
for item in range(0,5):
|
||||||
|
count = emojiList[item]["count"]
|
||||||
|
emoji = emojiList[item]["emoji"]
|
||||||
|
emoji_text += f"{count}x {emoji} " + chr(9553) + " "
|
||||||
|
emoji_text += " and more..."
|
||||||
|
|
||||||
|
if getReactions:
|
||||||
|
reactText = initial_react_text
|
||||||
|
for item in range(0,5):
|
||||||
|
count = reactList[item]["count"]
|
||||||
|
reaction = reactList[item]["reaction"]
|
||||||
|
reactText += f"{count}x {reaction} " + chr(9553) + " "
|
||||||
|
reactText += " and more..."
|
||||||
|
|
||||||
|
text = emoji_text + reactText
|
||||||
|
text = emojilib.emojize(text)
|
||||||
|
|
||||||
# print(text)
|
# print(text)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
req = requests.post(url + "/notes/create", json={
|
req = requests.post(url + "/notes/create", json={
|
||||||
"i": token,
|
"i": token,
|
||||||
"visibility": "public",
|
"visibility": noteVisibility,
|
||||||
"text": text
|
"text": text
|
||||||
})
|
})
|
||||||
req.raise_for_status()
|
req.raise_for_status()
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
emoji
|
emoji==1.6.3
|
||||||
python-dateutil
|
configparser~=5.2.0
|
||||||
|
requests~=2.27.1
|
Loading…
Reference in a new issue