Add places tags

This commit is contained in:
Marta Sienkiewicz 2026-01-11 19:25:04 +01:00
parent da95985e43
commit 84c24f200e
5 changed files with 96 additions and 47 deletions

View file

@ -5,29 +5,45 @@ import requests
import json import json
import csv import csv
class Discourse():
def __init__(self, url):
self.url = url
def get_category_data(self, category_id: str) -> requests.Response: DISCOURSE_URL = "https://kb.hs3.pl" # Database is hosted here
"""Get data related to a Discourse category""" CATEGORY_ID = 9 # Database category ID
class DiscourseDatabase():
def __init__(self):
data = self.get_category_data()
self.category_topics_csv(data)
def get_category_data(self) -> requests.Response:
"""Get data from a Discourse category"""
headers = { headers = {
"content-type": "application/json", "content-type": "application/json",
} }
url = f"{self.url}/c/{category_id}.json" url = f"{DISCOURSE_URL}/c/{CATEGORY_ID}.json"
print(f"Fetching data from {url}")
res = requests.get(url, headers) res = requests.get(url, headers)
res.raise_for_status() res.raise_for_status()
res_json = json.loads(res.text) res_json = json.loads(res.text)
return res_json return res_json
def category_topics_csv(self, category_id: str) -> requests.Response: def category_topics_csv(self, category_data) -> None:
"""Save category topics to a csv file""" """Save category topics to a csv file"""
cat_data = self.get_category_data(category_id) columns = ["id", "title", "place", "tags"]
columns = ["id", "title", "tags"] records = category_data["topic_list"]["topics"]
with open('zasoby.csv', 'w', encoding='UTF8') as f: with open('zasoby.csv', 'w', encoding='UTF8') as f:
write = csv.writer(f) write = csv.writer(f)
write.writerow(columns) write.writerow(columns)
for topic in cat_data["topic_list"]["topics"]: for topic in records:
html_url = f'<a href="{self.url}t/{topic["id"]}">{topic["title"]}</a>' html_url = f'<a href="{DISCOURSE_URL}/t/{topic["id"]}">{topic["title"]}</a>'
write.writerow([topic["id"], html_url, topic["tags"]]) place = self.get_place(topic)
write.writerow([topic["id"], html_url, place, topic["tags"]])
print(f"New zasoby.csv generated with {len(records)} records")
def get_place(self, topic):
"""Get place of a topic"""
places = ["cow-work", "garage", "workshop"]
for place in places:
if place in topic["tags"]:
return f'<a href="https://kb.hs3.pl/tag/{place}">{place}</a>'
return "unknown"

View file

@ -29,6 +29,8 @@
<td>title</td> <td>title</td>
<td>place</td>
<td>tags</td> <td>tags</td>
</tr> </tr>
@ -41,6 +43,8 @@
<td><a href="https://kb.hs3.pl/t/45">Jak stworzyć nowy wpis do bazy zasobów Hackerspace Trójmiasto?</a></td> <td><a href="https://kb.hs3.pl/t/45">Jak stworzyć nowy wpis do bazy zasobów Hackerspace Trójmiasto?</a></td>
<td>unknown</td>
<td>[]</td> <td>[]</td>
</tr> </tr>
@ -51,6 +55,8 @@
<td><a href="https://kb.hs3.pl/t/20">O kategorii: Baza Wiedzy Hackerspace'u</a></td> <td><a href="https://kb.hs3.pl/t/20">O kategorii: Baza Wiedzy Hackerspace'u</a></td>
<td>unknown</td>
<td>[]</td> <td>[]</td>
</tr> </tr>
@ -61,6 +67,8 @@
<td><a href="https://kb.hs3.pl/t/108">PC Engines APU2 Router Box</a></td> <td><a href="https://kb.hs3.pl/t/108">PC Engines APU2 Router Box</a></td>
<td><a href="https://kb.hs3.pl/tag/cow-work">cow-work</a></td>
<td>['cow-work', 'networking']</td> <td>['cow-work', 'networking']</td>
</tr> </tr>
@ -71,6 +79,8 @@
<td><a href="https://kb.hs3.pl/t/61">HS3 BOFH</a></td> <td><a href="https://kb.hs3.pl/t/61">HS3 BOFH</a></td>
<td><a href="https://kb.hs3.pl/tag/cow-work">cow-work</a></td>
<td>['cow-work', 'garage', 'events', 'bofh']</td> <td>['cow-work', 'garage', 'events', 'bofh']</td>
</tr> </tr>
@ -81,6 +91,8 @@
<td><a href="https://kb.hs3.pl/t/93">King Bob</a></td> <td><a href="https://kb.hs3.pl/t/93">King Bob</a></td>
<td><a href="https://kb.hs3.pl/tag/cow-work">cow-work</a></td>
<td>['cow-work']</td> <td>['cow-work']</td>
</tr> </tr>
@ -91,6 +103,8 @@
<td><a href="https://kb.hs3.pl/t/92">Drukarka 3D Creality K1 Max</a></td> <td><a href="https://kb.hs3.pl/t/92">Drukarka 3D Creality K1 Max</a></td>
<td><a href="https://kb.hs3.pl/tag/workshop">workshop</a></td>
<td>['tools', 'workshop', '3d-print']</td> <td>['tools', 'workshop', '3d-print']</td>
</tr> </tr>
@ -101,6 +115,8 @@
<td><a href="https://kb.hs3.pl/t/91">Drukarka 3D Creality Ender 3</a></td> <td><a href="https://kb.hs3.pl/t/91">Drukarka 3D Creality Ender 3</a></td>
<td><a href="https://kb.hs3.pl/tag/workshop">workshop</a></td>
<td>['tools', 'workshop', '3d-print']</td> <td>['tools', 'workshop', '3d-print']</td>
</tr> </tr>
@ -111,6 +127,8 @@
<td><a href="https://kb.hs3.pl/t/90">Chciejlista</a></td> <td><a href="https://kb.hs3.pl/t/90">Chciejlista</a></td>
<td>unknown</td>
<td>[]</td> <td>[]</td>
</tr> </tr>
@ -121,6 +139,8 @@
<td><a href="https://kb.hs3.pl/t/85">Komu powinien służyć Spejs</a></td> <td><a href="https://kb.hs3.pl/t/85">Komu powinien służyć Spejs</a></td>
<td>unknown</td>
<td>[]</td> <td>[]</td>
</tr> </tr>
@ -131,6 +151,8 @@
<td><a href="https://kb.hs3.pl/t/84">Budżet</a></td> <td><a href="https://kb.hs3.pl/t/84">Budżet</a></td>
<td>unknown</td>
<td>[]</td> <td>[]</td>
</tr> </tr>
@ -141,6 +163,8 @@
<td><a href="https://kb.hs3.pl/t/83">Hackerspace Dragon Dreaming</a></td> <td><a href="https://kb.hs3.pl/t/83">Hackerspace Dragon Dreaming</a></td>
<td>unknown</td>
<td>[]</td> <td>[]</td>
</tr> </tr>
@ -151,6 +175,8 @@
<td><a href="https://kb.hs3.pl/t/82">Biblioteka</a></td> <td><a href="https://kb.hs3.pl/t/82">Biblioteka</a></td>
<td><a href="https://kb.hs3.pl/tag/cow-work">cow-work</a></td>
<td>['cow-work', 'books']</td> <td>['cow-work', 'books']</td>
</tr> </tr>
@ -161,6 +187,8 @@
<td><a href="https://kb.hs3.pl/t/66">Apteczki</a></td> <td><a href="https://kb.hs3.pl/t/66">Apteczki</a></td>
<td><a href="https://kb.hs3.pl/tag/cow-work">cow-work</a></td>
<td>['cow-work', 'garage', 'bhp']</td> <td>['cow-work', 'garage', 'bhp']</td>
</tr> </tr>
@ -171,6 +199,8 @@
<td><a href="https://kb.hs3.pl/t/44">Brayton Power</a></td> <td><a href="https://kb.hs3.pl/t/44">Brayton Power</a></td>
<td><a href="https://kb.hs3.pl/tag/garage">garage</a></td>
<td>['garage', 'projects']</td> <td>['garage', 'projects']</td>
</tr> </tr>
@ -181,6 +211,8 @@
<td><a href="https://kb.hs3.pl/t/52">Evil Submarine</a></td> <td><a href="https://kb.hs3.pl/t/52">Evil Submarine</a></td>
<td><a href="https://kb.hs3.pl/tag/cow-work">cow-work</a></td>
<td>['cow-work', 'projects']</td> <td>['cow-work', 'projects']</td>
</tr> </tr>
@ -191,6 +223,8 @@
<td><a href="https://kb.hs3.pl/t/50">Infinity mirror (duże)</a></td> <td><a href="https://kb.hs3.pl/t/50">Infinity mirror (duże)</a></td>
<td><a href="https://kb.hs3.pl/tag/garage">garage</a></td>
<td>['garage', 'projects']</td> <td>['garage', 'projects']</td>
</tr> </tr>
@ -201,6 +235,8 @@
<td><a href="https://kb.hs3.pl/t/47">Cricut Maker 3 ploter tnący</a></td> <td><a href="https://kb.hs3.pl/t/47">Cricut Maker 3 ploter tnący</a></td>
<td><a href="https://kb.hs3.pl/tag/workshop">workshop</a></td>
<td>['tools', 'workshop']</td> <td>['tools', 'workshop']</td>
</tr> </tr>
@ -211,6 +247,8 @@
<td><a href="https://kb.hs3.pl/t/41">Wiertarka PSB 500 RE BOSCH</a></td> <td><a href="https://kb.hs3.pl/t/41">Wiertarka PSB 500 RE BOSCH</a></td>
<td><a href="https://kb.hs3.pl/tag/garage">garage</a></td>
<td>['garage', 'tools']</td> <td>['garage', 'tools']</td>
</tr> </tr>
@ -221,6 +259,8 @@
<td><a href="https://kb.hs3.pl/t/46">What the Duck</a></td> <td><a href="https://kb.hs3.pl/t/46">What the Duck</a></td>
<td><a href="https://kb.hs3.pl/tag/cow-work">cow-work</a></td>
<td>['cow-work', 'wled']</td> <td>['cow-work', 'wled']</td>
</tr> </tr>

18
main.py
View file

@ -1,23 +1,19 @@
DISCOURSE_URL = "https://kb.hs3.pl/" # Database is hosted here
DISCOURSE_CATEGORY = 9 # Database is stored in this Discourse category
import os, shutil import os, shutil
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
import pandas as pd import pandas as pd
from discourse import DiscourseDatabase
from discourse import Discourse
def generate_dashboard(): def generate_dashboard():
"""Generate dashboard from zasoby.csv file""" """Generate dashboard from zasoby.csv file"""
print("Generating HTML dashboard")
website_folder = "docs" website_folder = "docs"
data = pd.read_csv("zasoby.csv") data = pd.read_csv("zasoby.csv")
env = Environment(loader=FileSystemLoader("template")) env = Environment(loader=FileSystemLoader("template"))
print("Removing old website files")
shutil.rmtree(f"./{website_folder}") shutil.rmtree(f"./{website_folder}")
os.mkdir(f"./{website_folder}") os.mkdir(f"./{website_folder}")
print("Creating a new website")
shutil.copytree("template/static", f"{website_folder}/static") shutil.copytree("template/static", f"{website_folder}/static")
print("Creating page to static file.")
template = env.get_template("_main_layout.html") template = env.get_template("_main_layout.html")
with open(f"{website_folder}/index.html", "w+", encoding="utf-8") as file: with open(f"{website_folder}/index.html", "w+", encoding="utf-8") as file:
header_row = data.columns.values.tolist() header_row = data.columns.values.tolist()
@ -27,10 +23,6 @@ def generate_dashboard():
if __name__ == "__main__": if __name__ == "__main__":
print(f"Discourse database: {DISCOURSE_URL}{DISCOURSE_CATEGORY}") DiscourseDatabase()
print("Fetching database data to zasoby.csv")
dis = Discourse(DISCOURSE_URL)
dis.category_topics_csv(DISCOURSE_CATEGORY)
print("Generating HTML dashboard")
generate_dashboard() generate_dashboard()
print("Done!") print("Done!")

View file

@ -18,7 +18,8 @@
{% block body %}{% endblock body %} {% block body %}{% endblock body %}
</body> </body>
<footer> <footer>
Created by <a href="https://github.com/MartaSien">Marta Sienkiewicz</a> Baza zasobów Hackerspace Trójmiasto <a href="https://github.com/MartaSien/hs3-baza-zasobow-dashboard">repository</a>
Author <a href="https://github.com/MartaSien">Marta Sienkiewicz</a>
</footer> </footer>
<!-- jQuery --> <!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script> <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>

View file

@ -1,20 +1,20 @@
id,title,tags id,title,place,tags
45,"<a href=""https://kb.hs3.pl/t/45"">Jak stworzyć nowy wpis do bazy zasobów Hackerspace Trójmiasto?</a>",[] 45,"<a href=""https://kb.hs3.pl/t/45"">Jak stworzyć nowy wpis do bazy zasobów Hackerspace Trójmiasto?</a>",unknown,[]
20,"<a href=""https://kb.hs3.pl/t/20"">O kategorii: Baza Wiedzy Hackerspace'u</a>",[] 20,"<a href=""https://kb.hs3.pl/t/20"">O kategorii: Baza Wiedzy Hackerspace'u</a>",unknown,[]
108,"<a href=""https://kb.hs3.pl/t/108"">PC Engines APU2 Router Box</a>","['cow-work', 'networking']" 108,"<a href=""https://kb.hs3.pl/t/108"">PC Engines APU2 Router Box</a>","<a href=""https://kb.hs3.pl/tag/cow-work"">cow-work</a>","['cow-work', 'networking']"
61,"<a href=""https://kb.hs3.pl/t/61"">HS3 BOFH</a>","['cow-work', 'garage', 'events', 'bofh']" 61,"<a href=""https://kb.hs3.pl/t/61"">HS3 BOFH</a>","<a href=""https://kb.hs3.pl/tag/cow-work"">cow-work</a>","['cow-work', 'garage', 'events', 'bofh']"
93,"<a href=""https://kb.hs3.pl/t/93"">King Bob</a>",['cow-work'] 93,"<a href=""https://kb.hs3.pl/t/93"">King Bob</a>","<a href=""https://kb.hs3.pl/tag/cow-work"">cow-work</a>",['cow-work']
92,"<a href=""https://kb.hs3.pl/t/92"">Drukarka 3D Creality K1 Max</a>","['tools', 'workshop', '3d-print']" 92,"<a href=""https://kb.hs3.pl/t/92"">Drukarka 3D Creality K1 Max</a>","<a href=""https://kb.hs3.pl/tag/workshop"">workshop</a>","['tools', 'workshop', '3d-print']"
91,"<a href=""https://kb.hs3.pl/t/91"">Drukarka 3D Creality Ender 3</a>","['tools', 'workshop', '3d-print']" 91,"<a href=""https://kb.hs3.pl/t/91"">Drukarka 3D Creality Ender 3</a>","<a href=""https://kb.hs3.pl/tag/workshop"">workshop</a>","['tools', 'workshop', '3d-print']"
90,"<a href=""https://kb.hs3.pl/t/90"">Chciejlista</a>",[] 90,"<a href=""https://kb.hs3.pl/t/90"">Chciejlista</a>",unknown,[]
85,"<a href=""https://kb.hs3.pl/t/85"">Komu powinien służyć Spejs</a>",[] 85,"<a href=""https://kb.hs3.pl/t/85"">Komu powinien służyć Spejs</a>",unknown,[]
84,"<a href=""https://kb.hs3.pl/t/84"">Budżet</a>",[] 84,"<a href=""https://kb.hs3.pl/t/84"">Budżet</a>",unknown,[]
83,"<a href=""https://kb.hs3.pl/t/83"">Hackerspace Dragon Dreaming</a>",[] 83,"<a href=""https://kb.hs3.pl/t/83"">Hackerspace Dragon Dreaming</a>",unknown,[]
82,"<a href=""https://kb.hs3.pl/t/82"">Biblioteka</a>","['cow-work', 'books']" 82,"<a href=""https://kb.hs3.pl/t/82"">Biblioteka</a>","<a href=""https://kb.hs3.pl/tag/cow-work"">cow-work</a>","['cow-work', 'books']"
66,"<a href=""https://kb.hs3.pl/t/66"">Apteczki</a>","['cow-work', 'garage', 'bhp']" 66,"<a href=""https://kb.hs3.pl/t/66"">Apteczki</a>","<a href=""https://kb.hs3.pl/tag/cow-work"">cow-work</a>","['cow-work', 'garage', 'bhp']"
44,"<a href=""https://kb.hs3.pl/t/44"">Brayton Power</a>","['garage', 'projects']" 44,"<a href=""https://kb.hs3.pl/t/44"">Brayton Power</a>","<a href=""https://kb.hs3.pl/tag/garage"">garage</a>","['garage', 'projects']"
52,"<a href=""https://kb.hs3.pl/t/52"">Evil Submarine</a>","['cow-work', 'projects']" 52,"<a href=""https://kb.hs3.pl/t/52"">Evil Submarine</a>","<a href=""https://kb.hs3.pl/tag/cow-work"">cow-work</a>","['cow-work', 'projects']"
50,"<a href=""https://kb.hs3.pl/t/50"">Infinity mirror (duże)</a>","['garage', 'projects']" 50,"<a href=""https://kb.hs3.pl/t/50"">Infinity mirror (duże)</a>","<a href=""https://kb.hs3.pl/tag/garage"">garage</a>","['garage', 'projects']"
47,"<a href=""https://kb.hs3.pl/t/47"">Cricut Maker 3 ploter tnący</a>","['tools', 'workshop']" 47,"<a href=""https://kb.hs3.pl/t/47"">Cricut Maker 3 ploter tnący</a>","<a href=""https://kb.hs3.pl/tag/workshop"">workshop</a>","['tools', 'workshop']"
41,"<a href=""https://kb.hs3.pl/t/41"">Wiertarka PSB 500 RE BOSCH</a>","['garage', 'tools']" 41,"<a href=""https://kb.hs3.pl/t/41"">Wiertarka PSB 500 RE BOSCH</a>","<a href=""https://kb.hs3.pl/tag/garage"">garage</a>","['garage', 'tools']"
46,"<a href=""https://kb.hs3.pl/t/46"">What the Duck</a>","['cow-work', 'wled']" 46,"<a href=""https://kb.hs3.pl/t/46"">What the Duck</a>","<a href=""https://kb.hs3.pl/tag/cow-work"">cow-work</a>","['cow-work', 'wled']"

Can't render this file because it contains an unexpected character in line 4 and column 101.