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:
Fotoente 2022-03-13 09:31:58 +01:00
parent 9402ce3c28
commit d506ea627d
6 changed files with 159 additions and 46 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
emojicount.cfg
miceco.cfg
roboduck.cfg

View file

@ -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`
```
emoji
python-dateutil
configparser
requests
```
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`
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
|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`
|user|`username`|The user you want to read the notes from|
|token|`String`|The token for your bot. Needs permission to write notes|
|getReaction|`Boolean`|Should reactions emojis be counted as well? `True` or `False`|
| 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` |
| user | `username` | The user you want to read the notes from |
| token | `String` | The token for your bot. Needs permission to write notes |
| 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
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.
#### 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.

View file

@ -3,3 +3,5 @@ instance=//DOMAIN.TLD//
user=//USERNAME//
token=//TOKEN HERE//
getReaction=True
ignoreEmojis=true
noteVisibility=public

15
ignoredemojis.txt Normal file
View file

@ -0,0 +1,15 @@
🟩
🟨
🟪
👹
🪄
🪙
🔸
🎉
🇩🇪
↙️
➡️

153
miceco.py
View file

@ -2,11 +2,11 @@ import configparser
import os
import re
import sys
import argparse
from datetime import *
# import dateutil.relativedelta
import requests
import emoji as emojilib
# TODO: Replace with emojis library!
def check_str_to_bool(input_text) -> bool:
@ -27,7 +27,15 @@ doubleList = []
text = ""
getReactions = False
configfilePath = os.path.join(os.path.dirname(__file__), 'miceco.cfg')
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')
else:
configfilePath = args.config
if not os.path.exists(configfilePath):
print("No config File found!")
@ -47,6 +55,33 @@ try:
except (TypeError, ValueError) as err:
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:
req = requests.post(url + "/users/show", json={"username": user, "host": None, "i": token})
req.raise_for_status()
@ -55,12 +90,24 @@ except requests.exceptions.HTTPError as err:
sys.exit(1)
userid = req.json()["id"]
nickname = req.json()["name"]
if req.json()["name"] is not None: # If no nickname is set, just user the username instead
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()
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))
todayMidnight = datetime.combine(today, time(0, 0, 0))
@ -93,12 +140,11 @@ while True:
sys.exit(1)
for jsonObj in req.json():
# textDict = jsonObj
noteList.append(jsonObj)
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"]
lastTimestamp = int(datetime.timestamp(datetime.strptime(lastTime, '%Y-%m-%dT%H:%M:%S.%f%z')) * 1000)
else:
@ -119,17 +165,17 @@ for element in noteList:
if emojis is not None:
for emoji in emojis:
if emoji["name"].find(
"@") == -1: # Only emojis from the own instance, because reactions will be in "emojis"
# too
if not emoji["name"] in doubleList:
doubleList.append(emoji["name"]) # Easy way to prevent a double emoji in the list.
emojiDict = {"emoji": ":" + emoji["name"] + ":", "count": 0}
if emoji["name"].find("@") == -1: # Only emojis from the own instance, because reactions will be in
# "emojis" too
emojiname = ":" + emoji["name"] + ":"
if emojiname not in doubleList:
doubleList.append(emojiname) # Easy way to prevent a double emoji in the list.
emojiDict = {"emoji": emojiname, "count": 0}
emojiList.append(emojiDict)
else:
continue
index = doubleList.index(emoji["name"])
index = doubleList.index(":" + emoji["name"] + ":")
emojiList[index]["count"] += element["text"].count(emojiList[index]["emoji"])
@ -142,19 +188,29 @@ for element in noteList:
UTF8text = element["text"] + " " + element["cw"]
else:
UTF8text = element["text"]
UTF8List = re.findall(emojilib.get_emoji_regexp(), UTF8text) # Find all UTF8 Emojis in Text and CW text
if len(UTF8List) > 0:
UTF8List = list(set(UTF8List))
UTF8ListRaw = re.findall(emojilib.get_emoji_regexp(), UTF8text) # Find all UTF8 Emojis in Text and CW text
UTF8text = emojilib.demojize(UTF8text)
# TODO urgent! replace "get_emoji_regexp"
if len(UTF8ListRaw) > 0:
UTF8List = list(set(UTF8ListRaw))
for emoji in UTF8List:
emoji = emojilib.demojize(emoji)
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}
emojiList.append(emojiDict)
index = doubleList.index(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 = []
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)
formerTimestamp = lastTimestamp
if not len(reactionList) <=1:
if not len(reactionList) <= 0:
lastTime = reactionList[len(reactionList) - 1]["createdAt"]
lastTimestamp = int(datetime.timestamp(datetime.strptime(lastTime, '%Y-%m-%dT%H:%M:%S.%f%z')) * 1000)
else:
@ -205,7 +261,6 @@ if getReactions:
reactList.append(emojiDict)
index = doubleList.index(react)
reactList[index]["count"] += 1
doubleList = []
@ -215,10 +270,13 @@ if getReactions:
for react in reactList: # Summarize the number of Reactions used
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:
reactText += str(reactionElement["count"]) + "x " + reactionElement["reaction"] + " " + chr(9553) + " "
count = reactionElement["count"]
reaction = reactionElement["reaction"]
reactText += f"{count}x {reaction} " + chr(9553) + " "
else:
reactText = "\n\nAnd didn't use any reactions."
else:
@ -228,25 +286,50 @@ for count in emojiList:
emojisTotal += count["count"]
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(
8203) + "\n\n" + chr(
9553) + " "
for element in emojiList:
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)
8203) + "\n\n" + chr(9553) + " "
text = initial_text
emoji_text = ""
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)
try:
req = requests.post(url + "/notes/create", json={
"i": token,
"visibility": "public",
"visibility": noteVisibility,
"text": text
})
req.raise_for_status()

View file

@ -1,2 +1,3 @@
emoji
python-dateutil
emoji==1.6.3
configparser~=5.2.0
requests~=2.27.1