HackaProfile 0.1.0__tar.gz → 1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/HackaProfile.egg-info/PKG-INFO +47 -8
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/HackaProfile.egg-info/requires.txt +1 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/PKG-INFO +47 -8
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/README.md +42 -7
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/pyproject.toml +7 -2
- hackaprofile-1.2.0/src/agent.py +100 -0
- hackaprofile-1.2.0/src/configTemplate/slack.hackaprofile.conf +61 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/src/frontend.py +87 -81
- hackaprofile-0.1.0/src/agent.py +0 -106
- hackaprofile-0.1.0/src/configTemplate/slack.hackaprofile.conf +0 -11
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/HackaProfile.egg-info/SOURCES.txt +0 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/HackaProfile.egg-info/dependency_links.txt +0 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/HackaProfile.egg-info/entry_points.txt +0 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/HackaProfile.egg-info/top_level.txt +0 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/setup.cfg +0 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/src/__init__.py +0 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/src/backend.py +0 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/src/configTemplate/agent.pid +0 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/src/configTemplate/hackaprofile.conf +0 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/src/configTemplate/hackatime.hackaprofile.conf +0 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/src/hackatimeOA.py +0 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/src/logTemplate/agent.log +0 -0
- {hackaprofile-0.1.0 → hackaprofile-1.2.0}/src/slackOA.py +0 -0
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: HackaProfile
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: A simple tool to automatically update Slack user profile based on their Hackatime/Wakatime heartbeat!
|
|
5
|
+
Project-URL: Repository, https://github.com/zibuyin/HackaProfile
|
|
6
|
+
Project-URL: Issues, https://github.com/zibuyin/HackaProfile/issues
|
|
7
|
+
Project-URL: Homepage, https://github.com/zibuyin/HackaProfile
|
|
5
8
|
Requires-Python: >=3.10
|
|
6
9
|
Description-Content-Type: text/markdown
|
|
7
10
|
Requires-Dist: annotated-doc==0.0.4
|
|
@@ -36,6 +39,7 @@ Requires-Dist: urllib3==2.7.0
|
|
|
36
39
|
Requires-Dist: wcwidth==0.8.1
|
|
37
40
|
Requires-Dist: Werkzeug==3.1.8
|
|
38
41
|
Requires-Dist: platformdirs==4.10.0
|
|
42
|
+
Requires-Dist: Jinja2==3.1.6
|
|
39
43
|
|
|
40
44
|
# HackaProfile
|
|
41
45
|
<img src="./assets/icon.png" width=30% alt="HackaProfile logo"></img>
|
|
@@ -48,13 +52,16 @@ Requires-Dist: platformdirs==4.10.0
|
|
|
48
52
|
- More features #TODO ~~(I don't wanna write README.md >:3)~~
|
|
49
53
|
|
|
50
54
|
## installation
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
### Install pipx
|
|
56
|
+
Check [pipx docs](https://pipx.pypa.io/stable/how-to/install-pipx/)
|
|
57
|
+
|
|
58
|
+
### Install Hackaprofile
|
|
59
|
+
```bash
|
|
60
|
+
pipx install hackaprofile
|
|
61
|
+
hackaprofile setup
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then follow the guided setup
|
|
58
65
|
|
|
59
66
|
## Placeholder Variables
|
|
60
67
|
A key feature of HackaProfile is that it allows you to customise your profile however you like (just like how you would change it on Slack/other platforms) BUT it **also allows you to use dynamic values** (i.e. Placeholder variables).
|
|
@@ -77,3 +84,35 @@ Example
|
|
|
77
84
|
- `{{entity}}` Path to the file workng on
|
|
78
85
|
- `{{machine}}` Current machine's hostname
|
|
79
86
|
|
|
87
|
+
## Logic Operators
|
|
88
|
+
You could not only dynamically set variables, but you could also **choose how they are represented dynamically*
|
|
89
|
+
|
|
90
|
+
### If Statements:
|
|
91
|
+
`{% if [condition] %} ... {% elif [condition] %} ... {% else %} ... {% endif %}
|
|
92
|
+
### Filters:
|
|
93
|
+
|
|
94
|
+
Transforms the string to lowercase
|
|
95
|
+
```
|
|
96
|
+
{{string|lower}}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Transforms the STRING to UPPERCASE
|
|
100
|
+
```
|
|
101
|
+
{{string|upper}}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Transforms the String into a Title format
|
|
105
|
+
```
|
|
106
|
+
{{string|title}}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Escaping:
|
|
110
|
+
```
|
|
111
|
+
{{ "string to be escaped" }}
|
|
112
|
+
```
|
|
113
|
+
or
|
|
114
|
+
```
|
|
115
|
+
{% raw %}
|
|
116
|
+
string to be escaped
|
|
117
|
+
{% endraw %}
|
|
118
|
+
```
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: HackaProfile
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: A simple tool to automatically update Slack user profile based on their Hackatime/Wakatime heartbeat!
|
|
5
|
+
Project-URL: Repository, https://github.com/zibuyin/HackaProfile
|
|
6
|
+
Project-URL: Issues, https://github.com/zibuyin/HackaProfile/issues
|
|
7
|
+
Project-URL: Homepage, https://github.com/zibuyin/HackaProfile
|
|
5
8
|
Requires-Python: >=3.10
|
|
6
9
|
Description-Content-Type: text/markdown
|
|
7
10
|
Requires-Dist: annotated-doc==0.0.4
|
|
@@ -36,6 +39,7 @@ Requires-Dist: urllib3==2.7.0
|
|
|
36
39
|
Requires-Dist: wcwidth==0.8.1
|
|
37
40
|
Requires-Dist: Werkzeug==3.1.8
|
|
38
41
|
Requires-Dist: platformdirs==4.10.0
|
|
42
|
+
Requires-Dist: Jinja2==3.1.6
|
|
39
43
|
|
|
40
44
|
# HackaProfile
|
|
41
45
|
<img src="./assets/icon.png" width=30% alt="HackaProfile logo"></img>
|
|
@@ -48,13 +52,16 @@ Requires-Dist: platformdirs==4.10.0
|
|
|
48
52
|
- More features #TODO ~~(I don't wanna write README.md >:3)~~
|
|
49
53
|
|
|
50
54
|
## installation
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
### Install pipx
|
|
56
|
+
Check [pipx docs](https://pipx.pypa.io/stable/how-to/install-pipx/)
|
|
57
|
+
|
|
58
|
+
### Install Hackaprofile
|
|
59
|
+
```bash
|
|
60
|
+
pipx install hackaprofile
|
|
61
|
+
hackaprofile setup
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then follow the guided setup
|
|
58
65
|
|
|
59
66
|
## Placeholder Variables
|
|
60
67
|
A key feature of HackaProfile is that it allows you to customise your profile however you like (just like how you would change it on Slack/other platforms) BUT it **also allows you to use dynamic values** (i.e. Placeholder variables).
|
|
@@ -77,3 +84,35 @@ Example
|
|
|
77
84
|
- `{{entity}}` Path to the file workng on
|
|
78
85
|
- `{{machine}}` Current machine's hostname
|
|
79
86
|
|
|
87
|
+
## Logic Operators
|
|
88
|
+
You could not only dynamically set variables, but you could also **choose how they are represented dynamically*
|
|
89
|
+
|
|
90
|
+
### If Statements:
|
|
91
|
+
`{% if [condition] %} ... {% elif [condition] %} ... {% else %} ... {% endif %}
|
|
92
|
+
### Filters:
|
|
93
|
+
|
|
94
|
+
Transforms the string to lowercase
|
|
95
|
+
```
|
|
96
|
+
{{string|lower}}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Transforms the STRING to UPPERCASE
|
|
100
|
+
```
|
|
101
|
+
{{string|upper}}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Transforms the String into a Title format
|
|
105
|
+
```
|
|
106
|
+
{{string|title}}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Escaping:
|
|
110
|
+
```
|
|
111
|
+
{{ "string to be escaped" }}
|
|
112
|
+
```
|
|
113
|
+
or
|
|
114
|
+
```
|
|
115
|
+
{% raw %}
|
|
116
|
+
string to be escaped
|
|
117
|
+
{% endraw %}
|
|
118
|
+
```
|
|
@@ -9,13 +9,16 @@
|
|
|
9
9
|
- More features #TODO ~~(I don't wanna write README.md >:3)~~
|
|
10
10
|
|
|
11
11
|
## installation
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
### Install pipx
|
|
13
|
+
Check [pipx docs](https://pipx.pypa.io/stable/how-to/install-pipx/)
|
|
14
|
+
|
|
15
|
+
### Install Hackaprofile
|
|
16
|
+
```bash
|
|
17
|
+
pipx install hackaprofile
|
|
18
|
+
hackaprofile setup
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Then follow the guided setup
|
|
19
22
|
|
|
20
23
|
## Placeholder Variables
|
|
21
24
|
A key feature of HackaProfile is that it allows you to customise your profile however you like (just like how you would change it on Slack/other platforms) BUT it **also allows you to use dynamic values** (i.e. Placeholder variables).
|
|
@@ -38,3 +41,35 @@ Example
|
|
|
38
41
|
- `{{entity}}` Path to the file workng on
|
|
39
42
|
- `{{machine}}` Current machine's hostname
|
|
40
43
|
|
|
44
|
+
## Logic Operators
|
|
45
|
+
You could not only dynamically set variables, but you could also **choose how they are represented dynamically*
|
|
46
|
+
|
|
47
|
+
### If Statements:
|
|
48
|
+
`{% if [condition] %} ... {% elif [condition] %} ... {% else %} ... {% endif %}
|
|
49
|
+
### Filters:
|
|
50
|
+
|
|
51
|
+
Transforms the string to lowercase
|
|
52
|
+
```
|
|
53
|
+
{{string|lower}}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Transforms the STRING to UPPERCASE
|
|
57
|
+
```
|
|
58
|
+
{{string|upper}}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Transforms the String into a Title format
|
|
62
|
+
```
|
|
63
|
+
{{string|title}}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Escaping:
|
|
67
|
+
```
|
|
68
|
+
{{ "string to be escaped" }}
|
|
69
|
+
```
|
|
70
|
+
or
|
|
71
|
+
```
|
|
72
|
+
{% raw %}
|
|
73
|
+
string to be escaped
|
|
74
|
+
{% endraw %}
|
|
75
|
+
```
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "HackaProfile"
|
|
7
|
-
version = "
|
|
7
|
+
version = "1.2.0"
|
|
8
8
|
description = "A simple tool to automatically update Slack user profile based on their Hackatime/Wakatime heartbeat!"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -41,8 +41,13 @@ dependencies = [
|
|
|
41
41
|
"wcwidth==0.8.1",
|
|
42
42
|
"Werkzeug==3.1.8",
|
|
43
43
|
"platformdirs==4.10.0",
|
|
44
|
-
|
|
44
|
+
"Jinja2==3.1.6",
|
|
45
45
|
|
|
46
|
+
]
|
|
47
|
+
[project.urls]
|
|
48
|
+
Repository = "https://github.com/zibuyin/HackaProfile"
|
|
49
|
+
Issues = "https://github.com/zibuyin/HackaProfile/issues"
|
|
50
|
+
Homepage = "https://github.com/zibuyin/HackaProfile"
|
|
46
51
|
[project.scripts]
|
|
47
52
|
hackaprofile = "src.frontend:app"
|
|
48
53
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import time
|
|
2
|
+
try:
|
|
3
|
+
from . import backend
|
|
4
|
+
except ImportError:
|
|
5
|
+
import backend
|
|
6
|
+
import dotenv
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import platformdirs
|
|
10
|
+
from jinja2 import Template
|
|
11
|
+
import logging
|
|
12
|
+
|
|
13
|
+
logging.basicConfig(
|
|
14
|
+
format='[%(asctime)s] (Line: %(lineno)d) %(message)s',
|
|
15
|
+
level=logging.INFO
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
print("***** WORKER AGENT STARTED *****")
|
|
19
|
+
hackatime = backend.hackatime()
|
|
20
|
+
slack = backend.slack()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
active_services = ["slack"]
|
|
24
|
+
interval = 10
|
|
25
|
+
HOME = Path.home()
|
|
26
|
+
CONFIG_DIR = Path(platformdirs.user_config_dir("hackaprofile"))
|
|
27
|
+
LOG_DIR = Path(platformdirs.user_log_dir("hackaprofile"))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# langauge = ""
|
|
31
|
+
|
|
32
|
+
pid = os.getpid()
|
|
33
|
+
with open(CONFIG_DIR / "agent.pid", "w") as f:
|
|
34
|
+
f.write(str(pid))
|
|
35
|
+
f.close()
|
|
36
|
+
|
|
37
|
+
def clean_value(value: str) -> str:
|
|
38
|
+
"""
|
|
39
|
+
Makes the values clean for slack (Value passed for `name` contained unallowed special characters)
|
|
40
|
+
"""
|
|
41
|
+
return value.replace("<", "").replace(">", "")
|
|
42
|
+
|
|
43
|
+
def parse_config(config: dict, map):
|
|
44
|
+
parsed_config = {}
|
|
45
|
+
for key, template_str in config.items():
|
|
46
|
+
template = Template(template_str)
|
|
47
|
+
result = template.render(**map)
|
|
48
|
+
|
|
49
|
+
# # if the config field is empty, don't append it
|
|
50
|
+
# if key == "status_expiration":
|
|
51
|
+
# parsed_value = int(parsed_value)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
parsed_config[key] = result
|
|
55
|
+
|
|
56
|
+
# print(parsed)
|
|
57
|
+
print("---Parsed Config---")
|
|
58
|
+
logging.info(parsed_config)
|
|
59
|
+
print("---EO Parsed Config---\n")
|
|
60
|
+
return parsed_config
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
while True:
|
|
64
|
+
json = hackatime.fetch_hb()
|
|
65
|
+
|
|
66
|
+
# for _, field in enumerate(json):
|
|
67
|
+
# key = field
|
|
68
|
+
# value = json.get(field, "")
|
|
69
|
+
|
|
70
|
+
# project =
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
map = {
|
|
74
|
+
"id": json.get("id", ""),
|
|
75
|
+
"created_at": json.get("created_at", ""),
|
|
76
|
+
"time": json.get("time", ""),
|
|
77
|
+
"category": json.get("category", ""),
|
|
78
|
+
"project": json.get("project", ""),
|
|
79
|
+
"language": json.get("language", ""),
|
|
80
|
+
"editor": json.get("editor", ""),
|
|
81
|
+
"operating_system": json.get("operating_system", ""),
|
|
82
|
+
"machine": json.get("machine", ""),
|
|
83
|
+
"entity": json.get("entity", "")
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
print(f'Language: {map["language"]}')
|
|
89
|
+
print("---HT HB---")
|
|
90
|
+
logging.info(json)
|
|
91
|
+
print("---EO HT HB---\n")
|
|
92
|
+
if "slack" in active_services:
|
|
93
|
+
print(slack.fetch_config())
|
|
94
|
+
config = parse_config(slack.fetch_config(), map)
|
|
95
|
+
print(config)
|
|
96
|
+
|
|
97
|
+
res = slack.set_profile(config)
|
|
98
|
+
logging.info(res)
|
|
99
|
+
print("==============================================================")
|
|
100
|
+
time.sleep(interval)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#--------------------------------------#
|
|
2
|
+
# Don't change this plz (it will break...)
|
|
3
|
+
client_id = "2210535565.11339190985360"
|
|
4
|
+
#--------------------------------------#
|
|
5
|
+
|
|
6
|
+
# Fill values by uncommenting the field ID line under each label.
|
|
7
|
+
# WARNING: An empty string WILL literally set that field to empty (i.e. clear it), comment out field you don't want to be automatically updated
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# Docs: https://docs.slack.dev/reference/methods/users.profile.set#profile-fields
|
|
11
|
+
|
|
12
|
+
# title =
|
|
13
|
+
# phone =
|
|
14
|
+
# real_name =
|
|
15
|
+
# display_name =
|
|
16
|
+
|
|
17
|
+
# Docs: https://docs.slack.dev/reference/methods/users.profile.set#status
|
|
18
|
+
|
|
19
|
+
# status_text =
|
|
20
|
+
# status_emoji =
|
|
21
|
+
|
|
22
|
+
# ONLY SET TO INT (See docs)
|
|
23
|
+
# status_expiration =
|
|
24
|
+
|
|
25
|
+
# status_clear_on_focus_end =
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Hackclub Slack specific
|
|
30
|
+
|
|
31
|
+
# Github URL
|
|
32
|
+
# Xf09V176UVK5 =
|
|
33
|
+
|
|
34
|
+
# Birthday (YYYY-MM-DD)
|
|
35
|
+
# Xf0A06G5MKJM =
|
|
36
|
+
|
|
37
|
+
# Dog or Cat or Infrastructure?
|
|
38
|
+
# Xf09VB64B1PE =
|
|
39
|
+
|
|
40
|
+
# PFP Credit
|
|
41
|
+
# Xf09V5HE0MU6 =
|
|
42
|
+
|
|
43
|
+
# Website
|
|
44
|
+
# Xf09V45UG8AZ =
|
|
45
|
+
|
|
46
|
+
# Fav Languages/Tools
|
|
47
|
+
# Xf09V1775W91 =
|
|
48
|
+
|
|
49
|
+
# Start Date (YYYY-MM-DD)
|
|
50
|
+
# Xf09UWTTJF6Z =
|
|
51
|
+
|
|
52
|
+
# Fandoms
|
|
53
|
+
# Xf0AC8RUMQCT =
|
|
54
|
+
|
|
55
|
+
# Favorite Emoji
|
|
56
|
+
# Xf0APVLWEUC8 =
|
|
57
|
+
|
|
58
|
+
# HAM Callsign
|
|
59
|
+
# Xf0A06G5TTKK =
|
|
60
|
+
|
|
61
|
+
# Check README.md
|
|
@@ -33,6 +33,7 @@ import sys
|
|
|
33
33
|
import psutil
|
|
34
34
|
import signal
|
|
35
35
|
import platformdirs
|
|
36
|
+
import shlex
|
|
36
37
|
|
|
37
38
|
console = Console()
|
|
38
39
|
|
|
@@ -136,82 +137,86 @@ def setup(force: Annotated[bool, typer.Option("--force")] = False):
|
|
|
136
137
|
"""
|
|
137
138
|
Guided setup of HackaProfile
|
|
138
139
|
"""
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
# Allow overwrite if set to force
|
|
158
|
-
shutil.copytree(Path(__file__).resolve().parent / "configTemplate", CONFIG_DIR, dirs_exist_ok=force)
|
|
159
|
-
rprint("[bold green]✓[/bold green] Config file setup done!")
|
|
160
|
-
except FileExistsError:
|
|
161
|
-
rprint("[bold green]✓[/bold green] Config file already exists!")
|
|
162
|
-
except Exception as e:
|
|
163
|
-
rprint(f"❌ Failed to setup config files: {e}")
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
# If no token stored
|
|
167
|
-
if force or not hackatime.status()["ok"]:
|
|
168
|
-
# hackatimeConfirm = Confirm.ask("[bold cyan]Do you want to authorize Hackatime (This will redirect you to OAuth page)", default=True)
|
|
169
|
-
hackatimeConfirm = questionary.confirm("Do you want to authorize Hackatime (This will redirect you to OAuth page)").ask()
|
|
170
|
-
if hackatimeConfirm:
|
|
171
|
-
with console.status("Authorizing Hackatime", spinner="dots"):
|
|
172
|
-
ok, hackatime_token = hackatime.authorize()
|
|
140
|
+
if force:
|
|
141
|
+
conf = Confirm.ask("[bold red]Setting --force will CLEAR ALL EXISTING CONFIG AND LOGS. Do you wish to continue?", default=False)
|
|
142
|
+
if conf:
|
|
143
|
+
console.clear()
|
|
144
|
+
# console.rule("HackaProfile")
|
|
145
|
+
rprint(Panel(Text("Welcome to HackaProfile\nyou will be guided on an easy setup of the tool!", justify="center")))
|
|
146
|
+
console.rule()
|
|
147
|
+
# rprint(force)
|
|
148
|
+
|
|
149
|
+
# Copy log files
|
|
150
|
+
try:
|
|
151
|
+
# Allow overwrite if set to force
|
|
152
|
+
shutil.copytree(Path(__file__).resolve().parent / "logTemplate", LOG_DIR, dirs_exist_ok=force)
|
|
153
|
+
rprint("[bold green]✓[/bold green] Log file setup done!")
|
|
154
|
+
except FileExistsError:
|
|
155
|
+
rprint("[bold green]✓[/bold green] Log file already exists!")
|
|
156
|
+
except Exception as e:
|
|
157
|
+
rprint(f"❌ Failed to setup log files: {e}")
|
|
173
158
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
rprint(
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
else:
|
|
184
|
-
rprint("[bold green]✓[/bold green] Hackatime already authorized!\n")
|
|
185
|
-
|
|
186
|
-
platforms = questionary.checkbox(
|
|
187
|
-
message="Please choose the platforms you want to link to",
|
|
188
|
-
choices=[
|
|
189
|
-
"Slack",
|
|
190
|
-
"Github"
|
|
191
|
-
]
|
|
192
|
-
).ask()
|
|
193
|
-
|
|
194
|
-
# Authorize the platforms
|
|
195
|
-
|
|
196
|
-
for platform in platforms:
|
|
197
|
-
# print("test")
|
|
198
|
-
cls = backend.platfroms.get(platform.lower())
|
|
199
|
-
if cls:
|
|
200
|
-
instance = cls()
|
|
201
|
-
with console.status(f"Authorizing {platform}", spinner="dots"):
|
|
202
|
-
ok, platform_token = instance.authorize()
|
|
203
|
-
if ok:
|
|
204
|
-
rprint(f"[bold green]✓[/bold green] {platform} authorized!")
|
|
159
|
+
# Copy config files
|
|
160
|
+
try:
|
|
161
|
+
# Allow overwrite if set to force
|
|
162
|
+
shutil.copytree(Path(__file__).resolve().parent / "configTemplate", CONFIG_DIR, dirs_exist_ok=force)
|
|
163
|
+
rprint("[bold green]✓[/bold green] Config file setup done!")
|
|
164
|
+
except FileExistsError:
|
|
165
|
+
rprint("[bold green]✓[/bold green] Config file already exists!")
|
|
166
|
+
except Exception as e:
|
|
167
|
+
rprint(f"❌ Failed to setup config files: {e}")
|
|
205
168
|
|
|
169
|
+
|
|
170
|
+
# If no token stored
|
|
171
|
+
if force or not hackatime.status()["ok"]:
|
|
172
|
+
# hackatimeConfirm = Confirm.ask("[bold cyan]Do you want to authorize Hackatime (This will redirect you to OAuth page)", default=True)
|
|
173
|
+
hackatimeConfirm = questionary.confirm("Do you want to authorize Hackatime (This will redirect you to OAuth page)").ask()
|
|
174
|
+
if hackatimeConfirm:
|
|
175
|
+
with console.status("Authorizing Hackatime", spinner="dots"):
|
|
176
|
+
ok, hackatime_token = hackatime.authorize()
|
|
177
|
+
|
|
178
|
+
if ok:
|
|
179
|
+
rprint("[bold green]✓[/bold green] Hackatime authorized!")
|
|
180
|
+
|
|
181
|
+
else :
|
|
182
|
+
rprint(f"[bold red]err: {str(hackatime_token)}")
|
|
183
|
+
else:
|
|
184
|
+
rprint("[bold red]err: HackaProfile could not function without Hackatime.")
|
|
185
|
+
typer.Abort()
|
|
186
|
+
# If already stored
|
|
206
187
|
else:
|
|
207
|
-
rprint(
|
|
188
|
+
rprint("[bold green]✓[/bold green] Hackatime already authorized!\n")
|
|
189
|
+
|
|
190
|
+
platforms = questionary.checkbox(
|
|
191
|
+
message="Please choose the platforms you want to link to",
|
|
192
|
+
choices=[
|
|
193
|
+
"Slack"
|
|
194
|
+
]
|
|
195
|
+
).ask()
|
|
196
|
+
|
|
197
|
+
# Authorize the platforms
|
|
208
198
|
|
|
199
|
+
for platform in platforms:
|
|
200
|
+
# print("test")
|
|
201
|
+
cls = backend.platfroms.get(platform.lower())
|
|
202
|
+
if cls:
|
|
203
|
+
instance = cls()
|
|
204
|
+
with console.status(f"Authorizing {platform}", spinner="dots"):
|
|
205
|
+
ok, platform_token = instance.authorize()
|
|
206
|
+
if ok:
|
|
207
|
+
rprint(f"[bold green]✓[/bold green] {platform} authorized!")
|
|
208
|
+
|
|
209
|
+
else:
|
|
210
|
+
rprint(f"[bold red]err: {str(platform_token)}")
|
|
211
|
+
|
|
212
|
+
else:
|
|
213
|
+
rprint("[bold red]err: Platform unsupported")
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
rprint("[bold green]✓[/bold green] Setup complete!\n\n1.Run [bold green]hackaprofile config \\[platform name(e.g. slack)][/bold green] to configure\n2.Run [bold green]hackaprofile start[/bold green] to start updating your profile automatically!")
|
|
209
217
|
else:
|
|
210
|
-
rprint("[bold red]
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
rprint("[bold green]✓[/bold green] Setup complete!\n\n1.Run [bold green]hackaprofile config \\[platform name][/bold green] to configure\n2.Run [bold green]hackaprofile start[/bold green] to start updating your profile automatically!")
|
|
214
|
-
|
|
218
|
+
rprint("[bold red]Aborted.")
|
|
219
|
+
|
|
215
220
|
class placeholderHighlighter(Highlighter):
|
|
216
221
|
def highlight(self, text) -> None:
|
|
217
222
|
text.highlight_regex(r"\{\{.*?\}\}", "bold yellow")
|
|
@@ -221,7 +226,7 @@ def config(platform: Annotated[str, typer.Argument]):
|
|
|
221
226
|
"""
|
|
222
227
|
Shows a structured preview of the config files for each of the platforms
|
|
223
228
|
"""
|
|
224
|
-
|
|
229
|
+
rprint("[bold red]Check README.md on how to configure HackaProfile!\n")
|
|
225
230
|
table = Table(
|
|
226
231
|
"Field",
|
|
227
232
|
"Value",
|
|
@@ -254,16 +259,16 @@ def config(platform: Annotated[str, typer.Argument]):
|
|
|
254
259
|
if option == "Exit":
|
|
255
260
|
typer.Exit()
|
|
256
261
|
elif option == "Edit":
|
|
257
|
-
path = str(CONFIG_DIR/ f"{platform}.hackaprofile.conf")
|
|
258
|
-
rprint(f"\n[bold
|
|
262
|
+
path = shlex.quote(str(CONFIG_DIR/ f"{platform}.hackaprofile.conf"))
|
|
263
|
+
rprint(f"\n[bold cyan]Open[/bold cyan] {path} [bold cyan]in your preferred editor!")
|
|
259
264
|
|
|
260
|
-
|
|
261
|
-
"Do you want to copy path to clipboard?",
|
|
262
|
-
default=False
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
pyperclip.copy(path)
|
|
266
|
-
rprint("[bold green]✓[/bold green] Copied!")
|
|
265
|
+
# cbConfirm = questionary.confirm(
|
|
266
|
+
# "Do you want to copy path to clipboard?",
|
|
267
|
+
# default=False
|
|
268
|
+
# ).ask()
|
|
269
|
+
# if cbConfirm:
|
|
270
|
+
# pyperclip.copy(path)
|
|
271
|
+
# rprint("[bold green]✓[/bold green] Copied!")
|
|
267
272
|
|
|
268
273
|
# with Live(table, refresh_per_second=4):
|
|
269
274
|
# console.clear()Path(__file__).resolve().parent.parent / "config" / f"{platform}.hackaprofile.conf"
|
|
@@ -354,6 +359,7 @@ def debug():
|
|
|
354
359
|
"""
|
|
355
360
|
print(CONFIG_DIR)
|
|
356
361
|
print(LOG_DIR)
|
|
362
|
+
rprint(slack.get_profile())
|
|
357
363
|
|
|
358
364
|
|
|
359
365
|
if __name__ == "__main__":
|
hackaprofile-0.1.0/src/agent.py
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
try:
|
|
3
|
-
from . import backend
|
|
4
|
-
except ImportError:
|
|
5
|
-
import backend
|
|
6
|
-
import dotenv
|
|
7
|
-
import os
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
import platformdirs
|
|
10
|
-
|
|
11
|
-
hackatime = backend.hackatime()
|
|
12
|
-
slack = backend.slack()
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
active_services = ["slack"]
|
|
16
|
-
interval = 20
|
|
17
|
-
HOME = Path.home()
|
|
18
|
-
CONFIG_DIR = Path(platformdirs.user_config_dir("hackaprofile"))
|
|
19
|
-
LOG_DIR = Path(platformdirs.user_log_dir("hackaprofile"))
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# langauge = ""
|
|
23
|
-
|
|
24
|
-
pid = os.getpid()
|
|
25
|
-
with open(CONFIG_DIR / "agent.pid", "w") as f:
|
|
26
|
-
f.write(str(pid))
|
|
27
|
-
f.close()
|
|
28
|
-
|
|
29
|
-
def clean_value(value: str) -> str:
|
|
30
|
-
"""
|
|
31
|
-
Makes the values clean for slack (Value passed for `name` contained unallowed special characters)
|
|
32
|
-
"""
|
|
33
|
-
return value.replace("<", "").replace(">", "")
|
|
34
|
-
|
|
35
|
-
def parse_config(config: dict, map):
|
|
36
|
-
parsed_config = {}
|
|
37
|
-
for _, field in enumerate(config):
|
|
38
|
-
key = field
|
|
39
|
-
template: str = config[field]
|
|
40
|
-
# Replace {{key}} placeholders directly from the map.
|
|
41
|
-
for map_key, map_value in map.items():
|
|
42
|
-
template = template.replace(map_key, str(map_value))
|
|
43
|
-
try:
|
|
44
|
-
parsed_value = clean_value(template.format_map(map))
|
|
45
|
-
|
|
46
|
-
# if the config field is empty, don't append it
|
|
47
|
-
if parsed_value != "":
|
|
48
|
-
parsed_config[key] = parsed_value
|
|
49
|
-
except KeyError:
|
|
50
|
-
pass
|
|
51
|
-
|
|
52
|
-
# print(parsed)
|
|
53
|
-
|
|
54
|
-
return parsed_config
|
|
55
|
-
|
|
56
|
-
while True:
|
|
57
|
-
json = hackatime.fetch_hb()
|
|
58
|
-
|
|
59
|
-
# for _, field in enumerate(json):
|
|
60
|
-
# key = field
|
|
61
|
-
# value = json.get(field, "")
|
|
62
|
-
|
|
63
|
-
# project =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
map = {
|
|
67
|
-
"{{id}}": json.get("id", ""),
|
|
68
|
-
"{{created_at}}": json.get("created_at", ""),
|
|
69
|
-
"{{time}}": json.get("time", ""),
|
|
70
|
-
"{{category}}": json.get("category", ""),
|
|
71
|
-
"{{project}}": json.get("project", ""),
|
|
72
|
-
"{{language}}": json.get("language", ""),
|
|
73
|
-
"{{editor}}": json.get("editor", ""),
|
|
74
|
-
"{{operating_system}}": json.get("operating_system", ""),
|
|
75
|
-
"{{machine}}": json.get("machine", ""),
|
|
76
|
-
"{{entity}}": json.get("entity", "")
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
print(f'Language: {map["{{language}}"]}')
|
|
82
|
-
print(json)
|
|
83
|
-
|
|
84
|
-
if "slack" in active_services:
|
|
85
|
-
print(slack.fetch_config())
|
|
86
|
-
config = parse_config(slack.fetch_config(), map)
|
|
87
|
-
print(config)
|
|
88
|
-
|
|
89
|
-
res = slack.set_profile(config)
|
|
90
|
-
print(res)
|
|
91
|
-
# for _, field in enumerate(slack_config):
|
|
92
|
-
# print((field, slack_config[field]))
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
# slack.set_profile(
|
|
96
|
-
# profile={
|
|
97
|
-
# "status_text": "test status text",
|
|
98
|
-
# "status_emoji": ":67:",
|
|
99
|
-
# "status_expiration": 0
|
|
100
|
-
# })
|
|
101
|
-
print("---")
|
|
102
|
-
time.sleep(interval)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
#
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|