diff --git a/.gitignore b/.gitignore index 194e575..a20cca0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ emojicount.cfg miceco.cfg +roboduck.cfg diff --git a/README.md b/README.md index 6f05f0e..4a6ec06 100644 --- a/README.md +++ b/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` ``` 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.
Without this flag `miceco.cfg` will be used. | + | `-i` | `--ignored` | Which emojis should be ignored.
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
`folowers`: only visible for your followers
`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. diff --git a/example-miceco.cfg b/example-miceco.cfg index bdd06b5..a92afa4 100644 --- a/example-miceco.cfg +++ b/example-miceco.cfg @@ -2,4 +2,6 @@ instance=//DOMAIN.TLD// user=//USERNAME// token=//TOKEN HERE// -getReaction=True \ No newline at end of file +getReaction=True +ignoreEmojis=true +noteVisibility=public \ No newline at end of file diff --git a/ignoredemojis.txt b/ignoredemojis.txt new file mode 100644 index 0000000..44641b8 --- /dev/null +++ b/ignoredemojis.txt @@ -0,0 +1,15 @@ +🟩 +⬜ +🟨 +🟪 +⚔ +👹 +🪄 +🪙 +🔸 +🎉 +🇩🇪 +↗ +⬇ +↙️ +➡️ diff --git a/miceco.py b/miceco.py index c19b14a..b6d978c 100644 --- a/miceco.py +++ b/miceco.py @@ -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() diff --git a/requirements.txt b/requirements.txt index de5340e..3b67ec1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ -emoji -python-dateutil \ No newline at end of file +emoji==1.6.3 +configparser~=5.2.0 +requests~=2.27.1 \ No newline at end of file