Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
f2711bd3c3
|
|||
|
aaa8774dea
|
|||
|
89f6d9b85c
|
|||
|
724fc33f87
|
|||
|
a863ae498d
|
|||
|
00768bd887
|
|||
|
5ba472f87a
|
|||
|
7d115e8b43
|
|||
|
6a69b2c4ba
|
|||
|
b958d6616b
|
|||
|
430cbb6c10
|
|||
|
7754449b8b
|
|||
|
a530ebae35
|
|||
|
662b462192
|
|||
|
1f5bf3fc02
|
|||
|
faf2ae3c5e
|
@@ -1,84 +1,262 @@
|
|||||||
# fedi_start
|
# fedi_start
|
||||||
|
|
||||||
Onboarding systém pro nové uživatele Mastodonu (CZ/SK komunita).
|
Onboarding průvodce pro [Mamutovo.cz](https://mamutovo.cz) – pomáhá nováčkům začít na Fediverse.
|
||||||
|
|
||||||
## Soubory
|
- **Web:** https://fedi.mamutovo.cz
|
||||||
|
- **Repo:** https://git.arch-linux.cz/Mamutovo/fedi_start
|
||||||
|
- **Účet:** [@archlinuxcz@mamutovo.cz](https://mamutovo.cz/@archlinuxcz)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Obsah projektu
|
||||||
|
|
||||||
| Soubor | Popis |
|
| Soubor | Popis |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `start.html` | Úvodní onboarding stránka |
|
| `index.html` | Hlavní stránka |
|
||||||
| `accounts.html` | Interaktivní seznam CZ účtů s filtry |
|
| `start.html` | Krok za krokem onboarding pro nováčky |
|
||||||
| `accounts.json` | Data účtů (generováno skriptem) |
|
| `basics.html` | Základy Mastodonu |
|
||||||
| `starter-general.csv` | Starter pack pro import do Mastodonu |
|
| `accounts.html` | Interaktivní seznam CZ/SK účtů s filtry |
|
||||||
| `mastodon_cz_accounts.py` | Automatický sběr CZ/SK účtů |
|
| `apps.html` | Doporučené aplikace (Android / iOS / Web / Desktop) |
|
||||||
| `upload_surfer.sh` | Upload dat na Surfer |
|
| `accounts.json` | Data účtů (generováno skriptem, nahrává se na Surfer) |
|
||||||
|
| `accounts.csv` | Totéž v CSV (nahrává se na Surfer) |
|
||||||
|
| `manual_accounts.csv` | Ručně přidané účty (GTS instance a výjimky) |
|
||||||
|
| `starter-general.csv` | Starter pack – obecný – pro import do Mastodonu |
|
||||||
|
| `starter-tech.csv` | Starter pack – tech – pro import do Mastodonu |
|
||||||
|
| `mastodon_cz_accounts.py` | Hlavní skript – scraping CZ/SK účtů |
|
||||||
|
| `upload_surfer.sh` | Upload `accounts.json` a `accounts.csv` na Cloudron Surfer |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Lokální vývoj
|
||||||
|
|
||||||
## Lokální spuštění
|
|
||||||
```bash
|
```bash
|
||||||
|
# Spustí lokální HTTP server
|
||||||
python3 -m http.server 8080
|
python3 -m http.server 8080
|
||||||
# http://localhost:8080/accounts.html
|
# Otevři v prohlížeči: http://localhost:8080/
|
||||||
```
|
```
|
||||||
|
|
||||||
## Generování dat
|
---
|
||||||
```bash
|
|
||||||
python3 mastodon_cz_accounts.py --output .
|
## Skript `mastodon_cz_accounts.py`
|
||||||
|
|
||||||
|
Sbírá CZ/SK účty z Mastodonu a GoToSocial instancí, filtruje je a ukládá do `accounts.json` a `accounts.csv`.
|
||||||
|
|
||||||
|
### Jak funguje sběr dat
|
||||||
|
|
||||||
|
1. Pro každou instanci v `QUERY_INSTANCES` volá `/api/v1/directory` (veřejné Mastodon API).
|
||||||
|
2. Načte `manual_accounts.csv` a dohledá každý účet přes `/api/v1/accounts/lookup`.
|
||||||
|
3. Sloučí obojí, odstraní duplicity, seřadí a ořízne na `TOP_N` (výchozí 250) automatických účtů + všechny manuální.
|
||||||
|
|
||||||
|
### Kritéria pro zařazení (automatické účty)
|
||||||
|
|
||||||
|
| Podmínka | Hodnota |
|
||||||
|
|---|---|
|
||||||
|
| `discoverable = true` | Uživatel chce být nalezen |
|
||||||
|
| Aktivní za posledních | 90 dní |
|
||||||
|
| Min. počet příspěvků | 10 |
|
||||||
|
| Min. počet sledujících | 10 |
|
||||||
|
|
||||||
|
**Manuálně přidané účty** (`manual_accounts.csv`) jsou vždy zahrnuty bez ohledu na tato kritéria.
|
||||||
|
|
||||||
|
### Sledované instance
|
||||||
|
|
||||||
|
CZ/SK instance jsou v konstantě `QUERY_INSTANCES` v hlavičce skriptu:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
mastodonczech.cz, cztwitter.cz, witter.cz, mastodon.pirati.cz,
|
||||||
|
f.cz, lgbtcz.social, boskovice.social, mamutovo.cz,
|
||||||
|
gts.arch-linux.cz, kompost.cz, spondr.cz, skorpil.cz,
|
||||||
|
ajtaci.club, toot.whatever.cz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Spuštění
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Základní spuštění (výstup do aktuálního adresáře)
|
||||||
|
python3 mastodon_cz_accounts.py
|
||||||
|
|
||||||
|
# Výstup do konkrétního adresáře
|
||||||
|
python3 mastodon_cz_accounts.py --output /var/www/start/
|
||||||
|
|
||||||
|
# Omezení počtu účtů
|
||||||
|
python3 mastodon_cz_accounts.py --top 100
|
||||||
|
|
||||||
|
# Ladění
|
||||||
|
python3 mastodon_cz_accounts.py --debug
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Konfigurace `.env`
|
||||||
|
|
||||||
|
Vytvoř soubor `.env` v kořeni projektu (je v `.gitignore`, nikdy ho necommituj):
|
||||||
|
|
||||||
|
```ini
|
||||||
|
# Volitelný Mastodon token (pro vyšší rate limity)
|
||||||
|
MASTODON_TOKEN=tvuj_mastodon_token
|
||||||
|
|
||||||
|
# GoToSocial tokeny per-instance (viz sekce níže)
|
||||||
|
GTS_TOKEN_GTS_ARCH_LINUX_CZ=tvuj_token_zde
|
||||||
|
GTS_TOKEN_DALSI_INSTANCE_CZ=dalsi_token
|
||||||
|
|
||||||
|
# Surfer token pro upload na web
|
||||||
|
SURFER_TOKEN=tvuj_surfer_token
|
||||||
|
|
||||||
|
# Volitelně: jiný Surfer server (výchozí je fedi.mamutovo.cz)
|
||||||
|
# SURFER_SERVER=cloud.oscloud.cz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Proměnné prostředí
|
||||||
|
|
||||||
|
| Proměnná | Povinná | Popis |
|
||||||
|
|---|---|---|
|
||||||
|
| `MASTODON_TOKEN` | ne | Token pro Mastodon API (vyšší rate limity) |
|
||||||
|
| `GTS_TOKEN_<DOMAIN>` | pro GTS instance | Read token per GoToSocial instance |
|
||||||
|
| `SURFER_TOKEN` | pro upload | Token z Cloudron Surfer |
|
||||||
|
| `SURFER_SERVER` | ne | Server Surferu, pokud není výchozí |
|
||||||
|
|
||||||
|
Název proměnné pro GTS token se tvoří z domény – tečky a pomlčky se nahradí podtržítkem a vše se převede na VELKÁ PÍSMENA:
|
||||||
|
|
||||||
|
```
|
||||||
|
gts.arch-linux.cz → GTS_TOKEN_GTS_ARCH_LINUX_CZ
|
||||||
|
shimon.gts.example → GTS_TOKEN_SHIMON_GTS_EXAMPLE
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## GoToSocial instance – jak získat read token
|
||||||
|
|
||||||
|
GoToSocial nepodporuje veřejné `/api/v1/directory`, takže každá GTS instance potřebuje vlastní read token. Postup:
|
||||||
|
|
||||||
|
### 1. Přihlášení a vytvoření aplikace
|
||||||
|
|
||||||
|
Přihlas se na dané GTS instanci a jdi do **Settings → Applications → New application**.
|
||||||
|
|
||||||
|
Vyplň:
|
||||||
|
- **Název aplikace:** např. `fedi_start scraper`
|
||||||
|
- **Scopes:** zaškrtni pouze `read`
|
||||||
|
- Ostatní pole nech prázdná nebo vyplň libovolně
|
||||||
|
|
||||||
|
Uložíš aplikaci a GTS ti vygeneruje `client_id` a `client_secret`. Poznamenej si obojí.
|
||||||
|
|
||||||
|
### 2. Získání authorization code
|
||||||
|
|
||||||
|
Otevři v prohlížeči tuto URL (nahraď `INSTANCI.CZ` a `CLIENT_ID`):
|
||||||
|
|
||||||
|
```
|
||||||
|
https://INSTANCI.CZ/oauth/authorize?client_id=CLIENT_ID&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=read
|
||||||
|
```
|
||||||
|
|
||||||
|
Přihlášený prohlížeč zobrazí stránku s kódem – zkopíruj ho (jednorázový, platí jen chvíli).
|
||||||
|
|
||||||
|
### 3. Výměna code za access token
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST "https://INSTANCI.CZ/oauth/token" \
|
||||||
|
-d "client_id=CLIENT_ID" \
|
||||||
|
-d "client_secret=CLIENT_SECRET" \
|
||||||
|
-d "redirect_uri=urn:ietf:wg:oauth:2.0:oob" \
|
||||||
|
-d "grant_type=authorization_code" \
|
||||||
|
-d "code=AUTHORIZATION_CODE" \
|
||||||
|
-d "scope=read"
|
||||||
|
```
|
||||||
|
|
||||||
|
V odpovědi dostaneš JSON s `access_token`.
|
||||||
|
|
||||||
|
### 4. Přidání tokenu do `.env`
|
||||||
|
|
||||||
|
```ini
|
||||||
|
GTS_TOKEN_GTS_ARCH_LINUX_CZ=ziskany_access_token
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Ověření
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -H "Authorization: Bearer TVUJ_TOKEN" "https://INSTANCI.CZ/api/v1/accounts/verify_credentials"
|
||||||
|
```
|
||||||
|
|
||||||
|
Pokud vrátí JSON s tvým účtem, token funguje.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Přidání nového účtu
|
||||||
|
|
||||||
|
### Mastodon instance
|
||||||
|
|
||||||
|
Uživatel se zobrazí automaticky, pokud má v nastavení zapnuté:
|
||||||
|
|
||||||
|
> **Settings → Privacy → Appearance in search engines** (nebo česky „Zobrazovat profil ve vyhledávacích algoritmech")
|
||||||
|
|
||||||
|
A splňuje kritéria výše (aktivita, min. počet příspěvků atd.).
|
||||||
|
|
||||||
|
Pokud chceš účet přidat ručně bez ohledu na kritéria, přidej ho do `manual_accounts.csv`:
|
||||||
|
|
||||||
|
```csv
|
||||||
|
handle@instance.cz,true,false,
|
||||||
|
```
|
||||||
|
|
||||||
|
### GoToSocial instance
|
||||||
|
|
||||||
|
GTS nemá veřejný adresář, proto:
|
||||||
|
|
||||||
|
1. Získej read token (viz postup výše).
|
||||||
|
2. Přidej `GTS_TOKEN_<DOMAIN>=token` do `.env`.
|
||||||
|
3. Přidej konkrétní účty do `manual_accounts.csv` (GTS adresář je přístupný s tokenem, ale pro jistotu je lepší přidat je ručně).
|
||||||
|
4. Přidej instanci do `QUERY_INSTANCES` v `mastodon_cz_accounts.py`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Nasazení na VPS
|
## Nasazení na VPS
|
||||||
|
|
||||||
|
Projekt běží na VPS Hetzner v `/opt/fedi_start/`.
|
||||||
|
|
||||||
### Závislosti
|
### Závislosti
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip3 install requests python-dateutil
|
# Python (stdlib only, žádné externí balíčky)
|
||||||
|
python3 --version # 3.10+
|
||||||
|
|
||||||
|
# Node.js – Cloudron Surfer CLI
|
||||||
npm install -g cloudron-surfer
|
npm install -g cloudron-surfer
|
||||||
```
|
```
|
||||||
|
|
||||||
### Nastavení .env
|
### Nastavení na serveru
|
||||||
Vytvoř soubor `.env` v kořeni projektu:
|
|
||||||
```
|
```bash
|
||||||
MASTODON_TOKEN=tvuj_mastodon_token
|
git clone https://git.arch-linux.cz/Mamutovo/fedi_start /opt/fedi_start
|
||||||
GTS_TOKEN=tvuj_gts_token
|
cd /opt/fedi_start
|
||||||
SURFER_TOKEN=tvuj_surfer_token
|
cp .env.example .env # nebo vytvoř .env ručně
|
||||||
|
# Vyplň tokeny v .env
|
||||||
```
|
```
|
||||||
|
|
||||||
- **MASTODON_TOKEN** — přístupový token z nastavení Mastodon účtu (Settings → Development → New application)
|
### Cron
|
||||||
- **GTS_TOKEN** — token pro GoToSocial instanci
|
|
||||||
- **SURFER_TOKEN** — token z Cloudron Surfer (viz sekce Upload na Surfer)
|
|
||||||
|
|
||||||
## Cron
|
Automatická aktualizace 4× denně:
|
||||||
|
|
||||||
Automatické generování dat každý den ve 3:00:
|
|
||||||
```
|
```
|
||||||
0 3 * * * cd /opt/fedi_start && python3 mastodon_cz_accounts.py --output . && bash upload_surfer.sh
|
0 6,12,18,0 * * * cd /opt/fedi_start && python3 mastodon_cz_accounts.py --output . && bash upload_surfer.sh >> /var/log/fedi_start.log 2>&1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Upload na Surfer
|
## Upload na Surfer
|
||||||
|
|
||||||
### Instalace
|
[Cloudron Surfer](https://cloudron.io/store/io.cloudron.surfer.html) je jednoduchý statický file hosting.
|
||||||
```bash
|
|
||||||
npm install -g cloudron-surfer
|
|
||||||
```
|
|
||||||
|
|
||||||
### Konfigurace
|
### Ruční spuštění uploadu
|
||||||
```bash
|
|
||||||
surfer config --server fedi.mamutovo.cz --token TOKEN
|
|
||||||
```
|
|
||||||
|
|
||||||
### Spuštění uploadu
|
|
||||||
```bash
|
```bash
|
||||||
bash upload_surfer.sh
|
bash upload_surfer.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### CLI — manuální upload
|
Skript načte `SURFER_TOKEN` z `.env` a nahraje `accounts.json` + `accounts.csv` do kořene Surfer serveru.
|
||||||
|
|
||||||
|
### Manuální Surfer příkazy
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Nahrát konkrétní soubor do kořene
|
# Nahrát konkrétní soubory
|
||||||
surfer put -t $SURFER_TOKEN accounts.json /
|
|
||||||
|
|
||||||
# Nahrát více souborů najednou
|
|
||||||
surfer put -t $SURFER_TOKEN accounts.json accounts.csv /
|
surfer put -t $SURFER_TOKEN accounts.json accounts.csv /
|
||||||
|
|
||||||
# Nahrát celý adresář
|
|
||||||
surfer put -t $SURFER_TOKEN dist/ /
|
|
||||||
|
|
||||||
# Zobrazit obsah na serveru
|
# Zobrazit obsah na serveru
|
||||||
surfer get
|
surfer get
|
||||||
|
|
||||||
@@ -86,6 +264,30 @@ surfer get
|
|||||||
surfer del /accounts.json
|
surfer del /accounts.json
|
||||||
```
|
```
|
||||||
|
|
||||||
## Web
|
---
|
||||||
|
|
||||||
Stránka je dostupná na: https://fedi.mamutovo.cz
|
## Struktura dat `accounts.json`
|
||||||
|
|
||||||
|
Každý záznam v poli `accounts` obsahuje:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"handle": "uzivatel@instance.cz",
|
||||||
|
"display_name": "Zobrazované jméno",
|
||||||
|
"note": "Bio uživatele",
|
||||||
|
"followers": 123,
|
||||||
|
"following": 45,
|
||||||
|
"statuses": 678,
|
||||||
|
"last_active": "2024-03-15",
|
||||||
|
"avatar": "https://...",
|
||||||
|
"url": "https://instance.cz/@uzivatel",
|
||||||
|
"fields": [...],
|
||||||
|
"tags": ["linux", "opensource"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Přispívání
|
||||||
|
|
||||||
|
Pull requesty vítány. Repo: https://git.arch-linux.cz/Mamutovo/fedi_start
|
||||||
|
|||||||
+26
-2
@@ -614,6 +614,9 @@ select:focus { border-color: var(--accent); }
|
|||||||
<select id="categoryFilter">
|
<select id="categoryFilter">
|
||||||
<option value="">Všechny kategorie</option>
|
<option value="">Všechny kategorie</option>
|
||||||
</select>
|
</select>
|
||||||
|
<select id="instanceFilter">
|
||||||
|
<option value="">Všechny instance</option>
|
||||||
|
</select>
|
||||||
<select id="sortFilter">
|
<select id="sortFilter">
|
||||||
<option value="score">Nejvyšší skóre</option>
|
<option value="score">Nejvyšší skóre</option>
|
||||||
<option value="followers" selected>Nejvíce sledujících</option>
|
<option value="followers" selected>Nejvíce sledujících</option>
|
||||||
@@ -795,19 +798,22 @@ function filterByTag(tag) {
|
|||||||
function applyFilters() {
|
function applyFilters() {
|
||||||
const q = document.getElementById('searchInput').value.toLowerCase().trim();
|
const q = document.getElementById('searchInput').value.toLowerCase().trim();
|
||||||
const cat = document.getElementById('categoryFilter').value;
|
const cat = document.getElementById('categoryFilter').value;
|
||||||
|
const inst = document.getElementById('instanceFilter').value;
|
||||||
const sort = document.getElementById('sortFilter').value;
|
const sort = document.getElementById('sortFilter').value;
|
||||||
const activeTag = document.querySelector('.ftag.active')?.dataset.tag || '';
|
const activeTag = document.querySelector('.ftag.active')?.dataset.tag || '';
|
||||||
|
|
||||||
filtered = allAccounts.filter(a => {
|
filtered = allAccounts.filter(a => {
|
||||||
|
const handle = a.acct || a.handle || '';
|
||||||
const matchQ = !q ||
|
const matchQ = !q ||
|
||||||
a.name.toLowerCase().includes(q) ||
|
a.name.toLowerCase().includes(q) ||
|
||||||
(a.bio || '').toLowerCase().includes(q) ||
|
(a.bio || '').toLowerCase().includes(q) ||
|
||||||
(a.handle || '').toLowerCase().includes(q) ||
|
handle.toLowerCase().includes(q) ||
|
||||||
(a.tags || []).some(t => t.toLowerCase().includes(q));
|
(a.tags || []).some(t => t.toLowerCase().includes(q));
|
||||||
const matchCat = !cat || a.category === cat;
|
const matchCat = !cat || a.category === cat;
|
||||||
|
const matchInst = !inst || handle.split('@').pop() === inst;
|
||||||
const matchTag = !activeTag ||
|
const matchTag = !activeTag ||
|
||||||
(a.tags || []).some(t => t.toLowerCase().includes(activeTag.toLowerCase()));
|
(a.tags || []).some(t => t.toLowerCase().includes(activeTag.toLowerCase()));
|
||||||
return matchQ && matchCat && matchTag;
|
return matchQ && matchCat && matchInst && matchTag;
|
||||||
});
|
});
|
||||||
|
|
||||||
filtered.sort((a, b) => {
|
filtered.sort((a, b) => {
|
||||||
@@ -934,6 +940,7 @@ function downloadCSV(content, filename) {
|
|||||||
// ────────────────────────────────
|
// ────────────────────────────────
|
||||||
document.getElementById('searchInput').addEventListener('input', applyFilters);
|
document.getElementById('searchInput').addEventListener('input', applyFilters);
|
||||||
document.getElementById('categoryFilter').addEventListener('change', applyFilters);
|
document.getElementById('categoryFilter').addEventListener('change', applyFilters);
|
||||||
|
document.getElementById('instanceFilter').addEventListener('change', applyFilters);
|
||||||
document.getElementById('sortFilter').addEventListener('change', applyFilters);
|
document.getElementById('sortFilter').addEventListener('change', applyFilters);
|
||||||
|
|
||||||
document.querySelectorAll('.ftag').forEach(btn => {
|
document.querySelectorAll('.ftag').forEach(btn => {
|
||||||
@@ -993,6 +1000,23 @@ function buildDynamicUI() {
|
|||||||
sel.appendChild(opt);
|
sel.appendChild(opt);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- Instance select ---
|
||||||
|
const instanceCount = {};
|
||||||
|
allAccounts.forEach(a => {
|
||||||
|
const handle = a.acct || a.handle || '';
|
||||||
|
const instance = handle.includes('@') ? handle.split('@').pop() : '';
|
||||||
|
if (instance) instanceCount[instance] = (instanceCount[instance] || 0) + 1;
|
||||||
|
});
|
||||||
|
const instances = Object.keys(instanceCount).sort((a, b) => a.localeCompare(b, 'cs'));
|
||||||
|
const instSel = document.getElementById('instanceFilter');
|
||||||
|
instSel.innerHTML = '<option value="">Všechny instance</option>';
|
||||||
|
instances.forEach(instance => {
|
||||||
|
const opt = document.createElement('option');
|
||||||
|
opt.value = instance;
|
||||||
|
opt.textContent = `${instance} (${instanceCount[instance]})`;
|
||||||
|
instSel.appendChild(opt);
|
||||||
|
});
|
||||||
|
|
||||||
// --- Hashtag tlačítka – top 8 nejčastějších tagů ---
|
// --- Hashtag tlačítka – top 8 nejčastějších tagů ---
|
||||||
const tagCount = {};
|
const tagCount = {};
|
||||||
allAccounts.forEach(a => (a.tags || []).forEach(t => {
|
allAccounts.forEach(a => (a.tags || []).forEach(t => {
|
||||||
|
|||||||
+10
@@ -221,6 +221,16 @@
|
|||||||
<p><code>@Archos@mamutovo.cz</code> a <code>@archos@mamutovo.cz</code> jsou stejný účet. Velká a malá písmena nehrají roli.</p>
|
<p><code>@Archos@mamutovo.cz</code> a <code>@archos@mamutovo.cz</code> jsou stejný účet. Velká a malá písmena nehrají roli.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h2>Co je toot?</h2>
|
||||||
|
<p>Toot je příspěvek na Mastodonu – jako tweet na Twitteru. Může mít až 2000 znaků (na Mamutovo), obrázky, ankety nebo upozornění pro citlivý obsah. Veřejné tooty vidí celý Fediverse.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h2>Co je boost?</h2>
|
||||||
|
<p>Boost je přesdílení cizího tootu – jako retweet. Toot se zobrazí tvým sledujícím. Boost je způsob jak podpořit zajímavý obsah a pomoci mu se šířit. Na rozdíl od Twitteru nelze boost okomentovat.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2>Jak správně odpovídat</h2>
|
<h2>Jak správně odpovídat</h2>
|
||||||
<p>Při odpovědi na toot se automaticky přidají zmínky (@) všech lidí v konverzaci.</p>
|
<p>Při odpovědi na toot se automaticky přidají zmínky (@) všech lidí v konverzaci.</p>
|
||||||
|
|||||||
+8
-3
@@ -55,7 +55,6 @@ amarok@mastodonczech.cz,true,false,
|
|||||||
anlexcz@witter.cz,true,false,
|
anlexcz@witter.cz,true,false,
|
||||||
lacertacz@mastodonczech.cz,true,false,
|
lacertacz@mastodonczech.cz,true,false,
|
||||||
srandista@mastodonczech.cz,true,false,
|
srandista@mastodonczech.cz,true,false,
|
||||||
politiq@mastodon.arch-linux.cz,true,false,
|
|
||||||
aikencz@f.cz,true,false,
|
aikencz@f.cz,true,false,
|
||||||
sandruska93@mas.to,true,false,
|
sandruska93@mas.to,true,false,
|
||||||
karelcapek@mastodonczech.cz,true,false,
|
karelcapek@mastodonczech.cz,true,false,
|
||||||
@@ -97,7 +96,7 @@ nacelnik01@mamutovo.cz,true,false,
|
|||||||
sledge@mastodonczech.cz,true,false,
|
sledge@mastodonczech.cz,true,false,
|
||||||
tensob_@mastodonczech.cz,true,false
|
tensob_@mastodonczech.cz,true,false
|
||||||
archos@mamutovo.cz,true,false,
|
archos@mamutovo.cz,true,false,
|
||||||
archlinux@mamutovo.cz,true,false,
|
arch@gts.arch-linux.cz,true,false,
|
||||||
electric@vaclavpasek.cz,true,false,
|
electric@vaclavpasek.cz,true,false,
|
||||||
adamhavelka@mastodon.prorocketeers.com,true,false,
|
adamhavelka@mastodon.prorocketeers.com,true,false,
|
||||||
Kipe@mastodon.social,true,false,
|
Kipe@mastodon.social,true,false,
|
||||||
@@ -106,4 +105,10 @@ ozzelot@mstdn.social,true,false,
|
|||||||
j4n3z@mastodon.social,true,false,
|
j4n3z@mastodon.social,true,false,
|
||||||
prahou@merveilles.town,true,false,
|
prahou@merveilles.town,true,false,
|
||||||
mirek@rodina-sucha.cz,true,false,
|
mirek@rodina-sucha.cz,true,false,
|
||||||
sesivany@vivaldi.net,true,false,
|
sesivany@social.vivaldi.net,true,false,
|
||||||
|
jimmac@mastodon.social,true,false,
|
||||||
|
Oskar456@mastodon.social,true,false,
|
||||||
|
jmlich@fosstodon.org,true,false,
|
||||||
|
ronny@metalhead.club,true,false,
|
||||||
|
vancura@mastodon.design,true,false,
|
||||||
|
shimon@gts.shimonh.eu,true,false,
|
||||||
|
|||||||
|
+30
-5
@@ -37,6 +37,17 @@ def _load_tokens():
|
|||||||
break
|
break
|
||||||
if val:
|
if val:
|
||||||
tokens[key] = val.strip()
|
tokens[key] = val.strip()
|
||||||
|
# per-instance GTS tokeny: GTS_TOKEN_<DOMAIN>
|
||||||
|
for key, val in os.environ.items():
|
||||||
|
if key.startswith("GTS_TOKEN_") and val:
|
||||||
|
tokens[key] = val.strip()
|
||||||
|
for line in env_lines:
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith("GTS_TOKEN_") and "=" in line:
|
||||||
|
key, val = line.split("=", 1)
|
||||||
|
key = key.strip()
|
||||||
|
if key not in tokens and val.strip():
|
||||||
|
tokens[key] = val.strip()
|
||||||
# fallback: raw token value (legacy .env bez klíče)
|
# fallback: raw token value (legacy .env bez klíče)
|
||||||
if "MASTODON_TOKEN" not in tokens:
|
if "MASTODON_TOKEN" not in tokens:
|
||||||
for line in env_lines:
|
for line in env_lines:
|
||||||
@@ -47,13 +58,27 @@ def _load_tokens():
|
|||||||
return tokens
|
return tokens
|
||||||
|
|
||||||
_TOKENS = _load_tokens()
|
_TOKENS = _load_tokens()
|
||||||
MASTODON_TOKEN = _TOKENS.get("MASTODON_TOKEN")
|
MASTODON_TOKEN = _TOKENS.get("MASTODON_TOKEN")
|
||||||
GTS_TOKEN = _TOKENS.get("GTS_TOKEN")
|
GTS_TOKEN = _TOKENS.get("GTS_TOKEN") # legacy fallback
|
||||||
|
_GTS_INSTANCE_TOKENS = {k: v for k, v in _TOKENS.items() if k.startswith("GTS_TOKEN_")}
|
||||||
|
|
||||||
|
_gts_cache: dict[str, bool] = {}
|
||||||
|
|
||||||
|
def _is_gts(instance: str) -> bool:
|
||||||
|
if instance in _gts_cache:
|
||||||
|
return _gts_cache[instance]
|
||||||
|
info = api_get(f"https://{instance}/api/v1/instance")
|
||||||
|
version = (info or {}).get("version", "") if isinstance(info, dict) else ""
|
||||||
|
result = "git" in version or version.startswith("0.")
|
||||||
|
_gts_cache[instance] = result
|
||||||
|
return result
|
||||||
|
|
||||||
def _token_for(instance: str) -> str | None:
|
def _token_for(instance: str) -> str | None:
|
||||||
"""Vrátí GTS_TOKEN pro GoToSocial instance (obsahují 'gts.' v doméně), jinak MASTODON_TOKEN."""
|
if _is_gts(instance):
|
||||||
if GTS_TOKEN and "gts." in instance:
|
key = "GTS_TOKEN_" + re.sub(r"[.\-]", "_", instance).upper()
|
||||||
return GTS_TOKEN
|
token = _GTS_INSTANCE_TOKENS.get(key) or GTS_TOKEN
|
||||||
|
if token:
|
||||||
|
return token
|
||||||
return MASTODON_TOKEN
|
return MASTODON_TOKEN
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", datefmt="%H:%M:%S")
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", datefmt="%H:%M:%S")
|
||||||
|
|||||||
+7
-3
@@ -101,7 +101,7 @@
|
|||||||
/* --- CARDS GRID --- */
|
/* --- CARDS GRID --- */
|
||||||
.cards {
|
.cards {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,12 +484,16 @@ Rád/a poznám nové lidi 🙂 #Představení #novacek #cesky
|
|||||||
<p>Doporučené appky pro Android a iOS.</p>
|
<p>Doporučené appky pro Android a iOS.</p>
|
||||||
<a href="apps.html" class="btn btn-secondary">Zobrazit →</a>
|
<a href="apps.html" class="btn btn-secondary">Zobrazit →</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>💬 Chat v reálném čase</h3>
|
||||||
|
<p>Mastodon je na příspěvky, Matrix na chat. mxchat.cz je český Matrix server.</p>
|
||||||
|
<a href="https://web.mxchat.cz" class="btn btn-secondary" target="_blank">Otevřít →</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer-note">
|
<div class="footer-note">
|
||||||
Zasekl/a ses? Napiš na <a href="https://mamutovo.cz/@archos">@archos@mamutovo.cz</a> nebo
|
Tipy a triky: <a href="https://mamutovo.cz/tags/tip_mastodon">#tip_mastodon</a> · Potřebuješ pomoc? Napiš <a href="https://mamutovo.cz/@archos">@archos@mamutovo.cz</a><br>
|
||||||
se zeptej v <a href="https://mamutovo.cz/tags/pomoc">#pomoc</a>.<br>
|
|
||||||
Tato stránka je open source: <a href="https://git.arch-linux.cz/Mamutovo/fedi_start">Gitea</a> ·
|
Tato stránka je open source: <a href="https://git.arch-linux.cz/Mamutovo/fedi_start">Gitea</a> ·
|
||||||
<a href="https://oscloud.cz">oscloud.cz</a>
|
<a href="https://oscloud.cz">oscloud.cz</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user