mirror of https://gitlab.com/octtspacc/sitoctt
Agg. misti; Nuovo articolo: 🐕 Epicyon, piattaforma del Fediverso durata 2 giorni
This commit is contained in:
parent
7cae6da5aa
commit
07951f484c
|
@ -20,7 +20,24 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set Headings as Inline when inside Details Summaries and List Items */
|
/* Set Headings as Inline when inside Details Summaries and List Items */
|
||||||
Summary > H1, Summary > H2, Summary > H3, Summary > H4, Summary > H5, Summary > H6,
|
:Where(Summary, Li) > :Where(H1, H2, H3, H4, H5, H6) {
|
||||||
Li > H1, Li > H3, Li > H3, Li > H4, Li > H5, Li > H6 {
|
|
||||||
Display: Inline;
|
Display: Inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Animazioni per le desinenze */
|
||||||
|
.BlinkA {
|
||||||
|
Animation: BlinkerA 0.25s Step-Start Infinite;
|
||||||
|
}
|
||||||
|
@Keyframes BlinkerA {
|
||||||
|
0% {Position: Absolute; Visibility: Hidden;}
|
||||||
|
50% {Position: Static; Visibility: Visible;}
|
||||||
|
100% {Position: Absolute; Visibility: Hidden;}
|
||||||
|
}
|
||||||
|
.BlinkO {
|
||||||
|
Animation: BlinkerO 0.25s Step-Start Infinite;
|
||||||
|
}
|
||||||
|
@Keyframes BlinkerO {
|
||||||
|
0% {Position: Static; Visibility: Visible;}
|
||||||
|
50% {Position: Absolute; Visibility: Hidden;}
|
||||||
|
100% {Position: Static; Visibility: Visible;}
|
||||||
|
}
|
||||||
|
|
|
@ -8,23 +8,6 @@
|
||||||
Margin-Left: 3px;
|
Margin-Left: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.BlinkA {
|
|
||||||
Animation: BlinkerA 0.25s Step-Start Infinite;
|
|
||||||
}
|
|
||||||
@keyframes BlinkerA {
|
|
||||||
0% {Position: Absolute; Visibility: Hidden;}
|
|
||||||
50% {Position: Static; Visibility: Visible;}
|
|
||||||
100% {Position: Absolute; Visibility: Hidden;}
|
|
||||||
}
|
|
||||||
.BlinkO {
|
|
||||||
Animation: BlinkerO 0.25s Step-Start Infinite;
|
|
||||||
}
|
|
||||||
@keyframes BlinkerO {
|
|
||||||
0% {Position: Static; Visibility: Visible;}
|
|
||||||
50% {Position: Absolute; Visibility: Hidden;}
|
|
||||||
100% {Position: Static; Visibility: Visible;}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!-- Credits: https://codepen.io/jh3y/pen/WNrXqYz ---*/
|
/*!-- Credits: https://codepen.io/jh3y/pen/WNrXqYz ---*/
|
||||||
.WavyText {
|
.WavyText {
|
||||||
Text-Align: Center;
|
Text-Align: Center;
|
||||||
|
|
|
@ -211,10 +211,10 @@ Body {
|
||||||
Max-Height: Calc(40vh - (Var(--TitleBarHeight) * 2) - Var(--WindowMargin));
|
Max-Height: Calc(40vh - (Var(--TitleBarHeight) * 2) - Var(--WindowMargin));
|
||||||
}
|
}
|
||||||
|
|
||||||
#FeedWindow Ul Li, #TitlesWindow .WindowContent Ul Li, .TaskBarMenu Ul Li {
|
:Where(#FeedWindow, #TitlesWindow .WindowContent, .TaskBarMenu) Ul Li {
|
||||||
List-Style-Type: None !Important;
|
List-Style-Type: None !Important;
|
||||||
}
|
}
|
||||||
#FeedWindow Ul, #TitlesWindow Ul, .TaskBarMenu Ul {
|
:Where(#FeedWindow, #TitlesWindow, .TaskBarMenu) Ul {
|
||||||
Padding-Top: 0px;
|
Padding-Top: 0px;
|
||||||
Padding-Left: 8px;
|
Padding-Left: 8px;
|
||||||
Padding-Right: 4px;
|
Padding-Right: 4px;
|
||||||
|
@ -300,8 +300,7 @@ Body {
|
||||||
#DesktopCheck:Checked ~ Label > Span {
|
#DesktopCheck:Checked ~ Label > Span {
|
||||||
Background-Color: Var(--TitleBarBackground);
|
Background-Color: Var(--TitleBarBackground);
|
||||||
}
|
}
|
||||||
#DesktopCheck:Checked ~ .Window,
|
#DesktopCheck:Checked ~ :Where(.Window, * > .Window) {
|
||||||
#DesktopCheck:Checked ~ * > .Window {
|
|
||||||
Display: None;
|
Display: None;
|
||||||
Visibility: Hidden;
|
Visibility: Hidden;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
/*!
|
/*!
|
||||||
Borrowed from a running WriteFreely instance.
|
Borrowed from a running WriteFreely instance,
|
||||||
An header was missing from the file, but license is probably AGPL-3.0;
|
then minified to remove unused rules.
|
||||||
See https://github.com/writefreely/writefreely.
|
|
||||||
*/hr{border:0}header h1,header h2,header nav{display:inline}header nav a:hover{text-decoration:underline}body,p{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body nav#top-nav,header p.meta-note span{text-transform:uppercase}body{margin:0;padding:0;font-size:100%}header{margin:1em}header nav{margin:0 1em;line-height:2.4em}header nav a,header nav span{margin:0 0 0 1em}header nav a{color:#767676}header p.description{color:#444;font-size:1.1em;margin-top:.5em;line-height:1.5}header p.meta-note{color:#333;font-style:italic;margin-top:2em}header p.meta-note span{font-variant:small-caps;font-size:.9em;color:#666;font-style:normal}hr{height:1px;background:#ccc;max-width:40em;margin:4em auto;text-align:center}body{font-family:Lora,'Palatino Linotype','Book Antiqua','New York','DejaVu serif',serif}body{font-size-adjust:.5;background-color:#fff;color:#111}body h1 a,body header h2 a{color:#000;-moz-transition-duration:.2s;-webkit-transition-duration:.2s;-o-transition-duration:.2s;transition-duration:.2s}body h1 a:hover,body header h2 a:hover{color:#303030;text-decoration:none}body h1,body h2,body h3{line-height:1.2}body#post article{display:block;unicode-bidi:embed;white-space:pre}body#post article{margin-bottom:2em!important}body#post article h1,body#post article h2,body#post article h3,body#post article h4,body#post article h5,body#post article h6,body#post article ol,body#post article p,body#post article ul{display:inline;margin:0}body#post article hr+p,body#post article ol,body#post article ul{display:block;margin-top:-1rem;margin-bottom:-1rem}body#post article ol,body#post article ul{margin:2rem 0 -1rem}body#post article ol ol,body#post article ol ul,body#post article ul ol,body#post article ul ul{margin:1.25rem 0 -.5rem}body#post article li{margin-top:-.5rem;margin-bottom:-.5rem}body#post article h2#title{font-size:1.5em;display:block;margin-top:0;margin-bottom:1em}body#post article h1{font-size:1.5em}body#post article h2{font-size:1.4em}body#post audio,body#post img,body#post video{max-width:100%}body#post audio{width:100%;white-space:initial}body#post article hr{margin-top:0;margin-bottom:0}body nav#top-nav{font-family:'Open Sans','Segoe UI',Tahoma,Arial,sans-serif}body nav#top-nav{display:inline;position:absolute;top:1.5em;right:1.5em;font-size:.95rem}body nav#top-nav a{color:#777}body nav#top-nav a+a{margin-left:1em}.post-title a:link{color:#333}.post-title a:visited{color:#444}a{text-decoration:none}a:hover{text-decoration:underline}body#post article{max-width:40rem;margin:0 auto}body#post article.sans{line-height:1.5;white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}body#post article.sans,span.sans{font-family:'Open Sans','Segoe UI',Tahoma,Arial,sans-serif}article h2.post-title a[rel=nofollow]::after{content:'\a0 \2934'}li{line-height:1.5}#org-nav{font-family:'Open Sans','Segoe UI',Tahoma,Arial,sans-serif}@media only screen and (min-device-width:320px) and (max-device-width:480px){header{-moz-opacity:1;-khtml-opacity:1;-webkit-opacity:1;opacity:1}}@media only screen and (max-width:320px){header{-moz-opacity:1;-khtml-opacity:1;-webkit-opacity:1;opacity:1}}@media only screen and (min-device-width:768px) and (max-device-width:1024px){header{-moz-opacity:1;-khtml-opacity:1;-webkit-opacity:1;opacity:1}}@media print{h1{page-break-before:always}h1,h2,h3,h4,h5,h6{page-break-after:avoid}header{display:none}article#post-body{margin-top:2em;margin-left:0;margin-right:0}hr{border:1px solid #ccc}}#org-nav{font-size:1.1em;color:#888}#org-nav em,#org-nav strong{color:#000}#org-nav+h1{margin-top:.5em}#org-nav a:hover,#org-nav a:link,#org-nav a:visited{color:#767676}#org-nav a:first-child{margin-right:.25em}@media all and (max-width:600px){#target-name{max-width:98px;display:inline-block}}body#post header{margin:0 auto;padding:1em 2rem;-moz-opacity:.4;-khtml-opacity:.4;-webkit-opacity:.4;opacity:.4;-moz-transition-property:opacity;-webkit-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity;-moz-transition-duration:.4s;-webkit-transition-duration:.4s;-o-transition-duration:.4s;transition-duration:.4s}body#post header:hover{-moz-opacity:1;-khtml-opacity:1;-webkit-opacity:1;opacity:1}body#post header h1{font-size:1.6em}body#post article h2#title.dated{margin-bottom:.5em}article{padding:.5em 2rem 1.5em}body#post article{font-size:1.2em}@-moz-keyframes fadeIn{0%{opacity:0;position:static}100%{opacity:1}}@-webkit-keyframes fadeIn{0%{opacity:0;position:static}100%{opacity:1}}@-ms-keyframes fadeIn{0%{opacity:0;position:static}100%{opacity:1}}@-keyframes fadeIn{position:static}100%{opacity:1}100%{opacity:0;position:absolute;top:-1000px;left:-1000px}100%{opacity:0;position:absolute;top:-1000px;left:-1000px}100%{opacity:0;position:absolute;top:-1000px;left:-1000px}100%{opacity:0;position:absolute;top:-1000px;left:-1000px}
|
An header was missing from the file,
|
||||||
|
but license is probably AGPL-3.0;
|
||||||
|
see <https://github.com/writefreely/writefreely>.
|
||||||
|
*/
|
||||||
|
hr{border:0}header h1,header h2,header nav{display:inline}header nav a:hover{text-decoration:underline}body,p{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body nav#top-nav,header p.meta-note span{text-transform:uppercase}body{margin:0;padding:0;font-size:100%}header{margin:1em}header nav{margin:0 1em;line-height:2.4em}header nav a,header nav span{margin:0 0 0 1em}header nav a{color:#767676}header p.description{color:#444;font-size:1.1em;margin-top:.5em;line-height:1.5}header p.meta-note{color:#333;font-style:italic;margin-top:2em}header p.meta-note span{font-variant:small-caps;font-size:.9em;color:#666;font-style:normal}hr{height:1px;background:#ccc;max-width:40em;margin:4em auto;text-align:center}body{font-family:Lora,'Palatino Linotype','Book Antiqua','New York','DejaVu serif',serif}body{font-size-adjust:.5;background-color:#fff;color:#111}body h1 a,body header h2 a{color:#000;-moz-transition-duration:.2s;-webkit-transition-duration:.2s;-o-transition-duration:.2s;transition-duration:.2s}body h1 a:hover,body header h2 a:hover{color:#303030;text-decoration:none}body h1,body h2,body h3{line-height:1.2}body#post article{display:block;unicode-bidi:embed;white-space:pre}body#post article{margin-bottom:2em!important}body#post article h1,body#post article h2,body#post article h3,body#post article h4,body#post article h5,body#post article h6,body#post article ol,body#post article p,body#post article ul{display:inline;margin:0}body#post article hr+p,body#post article ol,body#post article ul{display:block;margin-top:-1rem;margin-bottom:-1rem}body#post article ol,body#post article ul{margin:2rem 0 -1rem}body#post article ol ol,body#post article ol ul,body#post article ul ol,body#post article ul ul{margin:1.25rem 0 -.5rem}body#post article li{margin-top:-.5rem;margin-bottom:-.5rem}body#post article h2#title{font-size:1.5em;display:block;margin-top:0;margin-bottom:1em}body#post article h1{font-size:1.5em}body#post article h2{font-size:1.4em}body#post audio,body#post img,body#post video{max-width:100%}body#post audio{width:100%;white-space:initial}body#post article hr{margin-top:0;margin-bottom:0}body nav#top-nav{font-family:'Open Sans','Segoe UI',Tahoma,Arial,sans-serif}body nav#top-nav{display:inline;position:absolute;top:1.5em;right:1.5em;font-size:.95rem}body nav#top-nav a{color:#777}body nav#top-nav a+a{margin-left:1em}.post-title a:link{color:#333}.post-title a:visited{color:#444}a{text-decoration:none}a:hover{text-decoration:underline}body#post article{max-width:40rem;margin:0 auto}body#post article.sans{line-height:1.5;white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}body#post article.sans,span.sans{font-family:'Open Sans','Segoe UI',Tahoma,Arial,sans-serif}article h2.post-title a[rel=nofollow]::after{content:'\a0 \2934'}li{line-height:1.5}#org-nav{font-family:'Open Sans','Segoe UI',Tahoma,Arial,sans-serif}@media only screen and (min-device-width:320px) and (max-device-width:480px){header{-moz-opacity:1;-khtml-opacity:1;-webkit-opacity:1;opacity:1}}@media only screen and (max-width:320px){header{-moz-opacity:1;-khtml-opacity:1;-webkit-opacity:1;opacity:1}}@media only screen and (min-device-width:768px) and (max-device-width:1024px){header{-moz-opacity:1;-khtml-opacity:1;-webkit-opacity:1;opacity:1}}@media print{h1{page-break-before:always}h1,h2,h3,h4,h5,h6{page-break-after:avoid}header{display:none}article#post-body{margin-top:2em;margin-left:0;margin-right:0}hr{border:1px solid #ccc}}#org-nav{font-size:1.1em;color:#888}#org-nav em,#org-nav strong{color:#000}#org-nav+h1{margin-top:.5em}#org-nav a:hover,#org-nav a:link,#org-nav a:visited{color:#767676}#org-nav a:first-child{margin-right:.25em}@media all and (max-width:600px){#target-name{max-width:98px;display:inline-block}}body#post header{margin:0 auto;padding:1em 2rem;-moz-opacity:.4;-khtml-opacity:.4;-webkit-opacity:.4;opacity:.4;-moz-transition-property:opacity;-webkit-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity;-moz-transition-duration:.4s;-webkit-transition-duration:.4s;-o-transition-duration:.4s;transition-duration:.4s}body#post header:hover{-moz-opacity:1;-khtml-opacity:1;-webkit-opacity:1;opacity:1}body#post header h1{font-size:1.6em}body#post article h2#title.dated{margin-bottom:.5em}article{padding:.5em 2rem 1.5em}body#post article{font-size:1.2em}@-moz-keyframes fadeIn{0%{opacity:0;position:static}100%{opacity:1}}@-webkit-keyframes fadeIn{0%{opacity:0;position:static}100%{opacity:1}}@-ms-keyframes fadeIn{0%{opacity:0;position:static}100%{opacity:1}}@-keyframes fadeIn{position:static}100%{opacity:1}100%{opacity:0;position:absolute;top:-1000px;left:-1000px}100%{opacity:0;position:absolute;top:-1000px;left:-1000px}100%{opacity:0;position:absolute;top:-1000px;left:-1000px}100%{opacity:0;position:absolute;top:-1000px;left:-1000px}
|
|
@ -54,8 +54,7 @@ Details Div {
|
||||||
Padding: 4px;
|
Padding: 4px;
|
||||||
}
|
}
|
||||||
.BorderBox,
|
.BorderBox,
|
||||||
.BorderBoxContainer > Div:Not(.NoBorderBox),
|
.BorderBoxContainer > :Where(Div, Details):Not(.NoBorderBox),
|
||||||
.BorderBoxContainer > Details:Not(.NoBorderBox),
|
|
||||||
Details Div Details:Not(.NoBorderBox) {
|
Details Div Details:Not(.NoBorderBox) {
|
||||||
Border: 2px Solid Purple;
|
Border: 2px Solid Purple;
|
||||||
Margin: 8px;
|
Margin: 8px;
|
||||||
|
@ -63,7 +62,7 @@ Details Div Details:Not(.NoBorderBox) {
|
||||||
}
|
}
|
||||||
|
|
||||||
A { Color: #D000D0; }
|
A { Color: #D000D0; }
|
||||||
Code A, .Code A { Color: #60D0D0; }
|
:Where(Code, .Code) A { Color: #60D0D0; }
|
||||||
|
|
||||||
H1, H2, H3, H4, H5, H6 {
|
H1, H2, H3, H4, H5, H6 {
|
||||||
Color: #503080;
|
Color: #503080;
|
||||||
|
@ -77,6 +76,12 @@ Table :Where(Td, Th, Tr) {
|
||||||
Padding: 4px;
|
Padding: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Blockquote, .Blockquote {
|
||||||
|
Margin-Left: 2em;
|
||||||
|
Padding-Left: 1em;
|
||||||
|
Border-Left: 3px Solid #85588C;
|
||||||
|
}
|
||||||
|
|
||||||
.ScrollBox, .ScrollBorderBox {
|
.ScrollBox, .ScrollBorderBox {
|
||||||
Padding: 8px;
|
Padding: 8px;
|
||||||
}
|
}
|
||||||
|
@ -100,11 +105,16 @@ Code:Not(Pre Code) {
|
||||||
Padding: 4px 4px 4px 4px;
|
Padding: 4px 4px 4px 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Video.SmallVideoQuote { Float:Left; }
|
||||||
|
Video.SmallVideoQuote + Blockquote {
|
||||||
|
Display: Inline-Block;
|
||||||
|
Margin-Top: 0;
|
||||||
|
Margin-Bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
#MainBox A:Not(
|
#MainBox A:Not(
|
||||||
.NoLinkLink, .NoLinkLink A,
|
.NoLinkLink,
|
||||||
.staticoso-SectionLink A,
|
:Where(.NoLinkLink, .staticoso-SectionLink, #StatCounter, #RingsDiv) A
|
||||||
#StatCounter A,
|
|
||||||
#RingsDiv A
|
|
||||||
):Before {
|
):Before {
|
||||||
Content: '🔗 ';
|
Content: '🔗 ';
|
||||||
}
|
}
|
||||||
|
@ -136,10 +146,11 @@ Header > P > A > Img {
|
||||||
}
|
}
|
||||||
|
|
||||||
A:Hover:Not(
|
A:Hover:Not(
|
||||||
H3 > A, H4 > A, H5 > A, H6 > A,
|
.NoABigger, .NoHoverLight,
|
||||||
.NoABigger, .NoABigger A,
|
:Where(.NoABigger, .NoHoverLight) A,
|
||||||
.NoHoverLight, .NoHoverLight A
|
:Where(H3, H4, H5, H6) > A
|
||||||
) {
|
),
|
||||||
|
:Where(.YesHoverLight, .YesHoverLight A):Hover {
|
||||||
Color: #EEDDFF !Important;
|
Color: #EEDDFF !Important;
|
||||||
Background: #700070 !Important;
|
Background: #700070 !Important;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +230,8 @@ IFrame {
|
||||||
.Img36 :Where(Img, Video) { Max-Height: 36vh !important; }
|
.Img36 :Where(Img, Video) { Max-Height: 36vh !important; }
|
||||||
.Img36 :Where(Img, Video):Hover { Max-Height: 64vh !important; }
|
.Img36 :Where(Img, Video):Hover { Max-Height: 64vh !important; }
|
||||||
|
|
||||||
.Center Img, .Center Video,
|
:Where(Img, Video).Center,
|
||||||
|
.Center :Where(Img, Video),
|
||||||
#MainBox P Img:Not(.NoImgCenter, .NoImgCenter Img),
|
#MainBox P Img:Not(.NoImgCenter, .NoImgCenter Img),
|
||||||
#MainBox P Video:Not(.NoImgCenter, .NoImgCenter Video) {
|
#MainBox P Video:Not(.NoImgCenter, .NoImgCenter Video) {
|
||||||
Display: Block;
|
Display: Block;
|
||||||
|
@ -376,21 +388,4 @@ H1, H2, H3, A, Img, Video, Summary {
|
||||||
Transition: 0.3s;
|
Transition: 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.BlinkA {
|
|
||||||
Animation: BlinkerA 0.25s Step-Start Infinite;
|
|
||||||
}
|
|
||||||
@keyframes BlinkerA {
|
|
||||||
0% {Position: Absolute; Visibility: Hidden;}
|
|
||||||
50% {Position: Static; Visibility: Visible;}
|
|
||||||
100% {Position: Absolute; Visibility: Hidden;}
|
|
||||||
}
|
|
||||||
.BlinkO {
|
|
||||||
Animation: BlinkerO 0.25s Step-Start Infinite;
|
|
||||||
}
|
|
||||||
@keyframes BlinkerO {
|
|
||||||
0% {Position: Static; Visibility: Visible;}
|
|
||||||
50% {Position: Absolute; Visibility: Hidden;}
|
|
||||||
100% {Position: Static; Visibility: Visible;}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------*/
|
/*--------------------------------------------------------*/
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// % HTMLTitle: <span class="twa twa-grinning-cat"><span>😺</span></span> Chi sono
|
// % HTMLTitle: <span class="twa twa-grinning-cat"><span>😺</span></span> Chi sono
|
||||||
// % Index: True
|
// % Index: True
|
||||||
// % Order: 20
|
// % Order: 20
|
||||||
// % UpdatedOn = 2022-11-17
|
// % UpdatedOn = 2022-12-24
|
||||||
// $ SelfhostLineBadge = <small style="Color:#CC0000; Font-Size:X-Small; Display:Inline-Block; Rotate:35deg; Margin-Left:-1.5em; Margin-Right:-1.5em;">SELFHOST!</small>
|
// $ SelfhostLineBadge = <small style="Color:#CC0000; Font-Size:X-Small; Display:Inline-Block; Rotate:35deg; Margin-Left:-1.5em; Margin-Right:-1.5em;">SELFHOST!</small>
|
||||||
|
|
||||||
# <span class="twa twa-grinning-cat"><span>😺</span></span> Chi sono?
|
# <span class="twa twa-grinning-cat"><span>😺</span></span> Chi sono?
|
||||||
|
|
|
@ -20,9 +20,7 @@ Per quelle 3 persone che vivono sotto le pietre <em>(e che non so come potrebber
|
||||||
In una <a href="https://youtu.be/efdN69QscAg" rel="noopener nofollow" target="_blank">scena del gioco</a>, <a href="https://typemoon.fandom.com/it/wiki/Nerone" rel="noopener nofollow" target="_blank">Nerone Claudio Cesare Augusto Germanico (non scherzo)</a> indossa un costume da <strong>Babbo Natale</strong>, e danza in giro per quello che credo sia un corridoio, cantando una <strong>parodia</strong> originale di <em>Jingle Bells</em>, di appena 4 strofe.</p>
|
In una <a href="https://youtu.be/efdN69QscAg" rel="noopener nofollow" target="_blank">scena del gioco</a>, <a href="https://typemoon.fandom.com/it/wiki/Nerone" rel="noopener nofollow" target="_blank">Nerone Claudio Cesare Augusto Germanico (non scherzo)</a> indossa un costume da <strong>Babbo Natale</strong>, e danza in giro per quello che credo sia un corridoio, cantando una <strong>parodia</strong> originale di <em>Jingle Bells</em>, di appena 4 strofe.</p>
|
||||||
|
|
||||||
|
|
||||||
<video src="[staticoso:CustomPath:Assets]/Media/Padoru/PadoruPadoru.webm" controls="true" muted="true" loop="true" autoplay="true">Il video della scena del gioco.</video>
|
<video class="SmallVideoQuote Blockquote NoImgCenter" title="Il video della scena del gioco." src="[staticoso:CustomPath:Assets]/Media/Padoru/PadoruPadoru.webm" [:videoelemargs-controlmuteloopauto:]="">Il video della scena del gioco.</video>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>HASHIRE SORI YO<br>
|
<p>HASHIRE SORI YO<br>
|
||||||
|
@ -139,6 +137,10 @@ Questo qui è il risultato, mi piace veramente un botto.</p>
|
||||||
|
|
||||||
<h2>[:HNotesRefsHTML:]</h2>
|
<h2>[:HNotesRefsHTML:]</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><strong>Aggiornamento</strong> del <strong>2022-12-24</strong>: Ho caricato alcune foto in più sulla storia su Pixelfed: <a href="https://pixelfed.uno/p/octo/512223099419845225" rel="noopener nofollow" target="_blank">pixelfed.uno/p/octo/512223099419845225</a>.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<div class="footnotes">
|
<div class="footnotes">
|
||||||
<ol>
|
<ol>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,238 @@
|
||||||
|
// % Title = 🐕🦺 Epicyon, piattaforma del Fediverso durata 2 giorni
|
||||||
|
// % CreatedOn = 2022-12-26
|
||||||
|
// % Downsync = /Posts/Epicyon-Piattaforma-del-Fediverso-Durata-2-Giorni.html
|
||||||
|
// % HTMLTitle = <span class="twa twa-service-dog twa-🐕🦺">🐕🦺<span></span></span> Epicyon, piattaforma del Fediverso durata 2 giorni
|
||||||
|
// % Image = [staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/Featured-LCD.png
|
||||||
|
// % Categories = Blog Internet
|
||||||
|
|
||||||
|
<h1><span class="twa twa-service-dog twa-🐕🦺">🐕🦺<span></span></span> Epicyon, piattaforma del Fediverso durata 2 giorni</h1>
|
||||||
|
|
||||||
|
<p>Ormai, si sa, più passa il tempo e più finisco con l'<strong>esplorare</strong> dettagli sempre più minuti del <strong>Fediverso</strong>.<br>
|
||||||
|
Oggi racconto un po' di una <strong>piattaforma</strong> di questo mondo abbastanza <strong>sconosciuta</strong>, e che aveva buone premesse, ma si è rivelata un buco nell'acqua: <strong>Epicyon</strong>.<br>
|
||||||
|
Prima di iniziare, però, vediamo in che <strong>situazione disperata</strong> ero finita.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<p>5 settimane fa avevo finalmente installato la mia istanza di Misskey, ad oggi una piattaforma di <strong>microblogging</strong> altamente rispettabile nel panorama <strong>ActivityPub</strong>, che negli ultimi tempi sta lentamente guadagnando sempre più utenti.<br>
|
||||||
|
Uno dei motivi per cui Misskey sta crescendo è sicuramente il suo essere <strong>più leggero</strong> di Mastodon, ed è anche per questo che ho inizialmente prediletto la sua installazione. Ahimè, il destino ha <strong>comunque</strong> voluto maltrattarmi, decidendo di far finire tutto in un <strong>gran fiasco</strong> (con prima uno piccolo, di assaggio).<br>
|
||||||
|
Senza entrare troppo nei dettagli - chi crede di volerli sapere può leggere le mie lagne fatte su Mastodon nelle giornate di <a href="https://mastodon.uno/@octo/109439207514394158" rel="noopener nofollow" target="_blank">Giovedì 1</a> e <a href="https://mastodon.uno/@octo/109508472717947364" rel="noopener nofollow" target="_blank">Martedì 13</a> <small>(è chiaramente non una coincidenza...)</small> (ma la discussione buona è partita <a href="https://mastodon.uno/@octo/109518037875867744" rel="noopener nofollow" target="_blank">2 giorni dopo</a>) di questo Dicembre, o aspettare un articolo che <em>forse</em> scriverò - dal fatidico giorno fino al 19 Dicembre sono stata di nuovo senza un'istanza <em>mia mia mia</em>. Di nuovo <strong>senza potere</strong>, poiché il mio <strong>regno</strong> era ridotto <strong>in cenere</strong>.</p>
|
||||||
|
|
||||||
|
<p>Dopo questa intera settimana, in cui ho provato e riprovato a rimettere in piedi il mio server, <strong>fallendo</strong> miseramente, <strong>ho capito</strong> chiaramente che <strong>serviva</strong> una riconfigurazione da capo, preferibilmente con qualche <strong>software più leggero</strong> di Misskey.<br>
|
||||||
|
È stato a questo punto che mi son detta "ma sì, proviamolo questo <strong>Epicyon</strong>; che cosa potrebbe mai andare storto?". Eh eh, che cosa...</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Un'occhiata ad Epicyon</h2>
|
||||||
|
|
||||||
|
<p><a href="https://epicyon.net" rel="noopener nofollow" target="_blank">Epicyon</a> lo avevo scoperto settimane fa, totalmente a caso, mentre cercavo qualcosa, non ricordo cosa, sul Web.</p>
|
||||||
|
|
||||||
|
<p>Quell'elenco di <strong>punti a favore</strong> che figura sulla pagina principale del sito immediatamente cattura la mia attenzione: uno stack tecnologico non sbrilluccicante o usato solo perché di tendenza, con <strong>poca complessità</strong> lato server (e quindi richiedente poche risorse lì), addirittura con <strong>zero JavaScript lato client</strong> (quindi l'applicazione non pesa virtualmente nulla), adatto per l'installazione sui <a href="https://it.wikipedia.org/wiki/Single-board_computer" rel="noopener nofollow" target="_blank">single-board computer</a>, pensato anche per i <a href="https://en.wikipedia.org/wiki/Text-based_web_browser" rel="noopener nofollow" target="_blank">browser con interfaccia terminale</a>... le <strong>premesse</strong> erano <strong>buone</strong>.</p>
|
||||||
|
|
||||||
|
<p>I vantaggi della <strong>tecnologia a bassa scala</strong> sono stati immediatamente messi in mostra da questo programmino: l'installazione è ammontata all'installare alcune dipendenze da apt, scaricare i sorgenti dalla repository, e creare le configurazioni per il <em>reverse proxy</em> (Nginx) e il sistema di avvio (systemd).<br>
|
||||||
|
Assolutamente zero problemi di percorso; <strong>le rogne</strong>, infatti, <strong>sono venute dopo!</strong></p>
|
||||||
|
|
||||||
|
<p>Creati i miei account - prima quello "<em>sysadmin</em>", che detiene i permessi di amministrazione e che uso per scrivere in qualità di amministratrice d'istanza, e poi quello personale - man mano che inizio ad orientarmi nell'applicazione, <strong>diversi problemi</strong> minori si accorgono della mia presenza e, come spiritelli, uno alla volta <strong>iniziano a manifestarsi</strong>.</p>
|
||||||
|
|
||||||
|
<h2>L'interfaccia utente</h2>
|
||||||
|
|
||||||
|
<p>Iniziamo dal<strong>l'interfaccia</strong>, che è la prima cosa con cui si fa i conti quando si usa qualunque applicazione; ebbene, <strong>è proprio strana</strong>!<br>
|
||||||
|
Una volta imparata <strong>non è difficile</strong>, <strong>però</strong> ha certe cose che sembrano fatte apposta per indurre in <strong>confusione</strong>.</p>
|
||||||
|
|
||||||
|
<p>Sulla pagina del proprio profilo si va cliccando il banner (che spreca spazio, mi sento di dire, rispetto ad un bottoncino) in alto alla home.<br>
|
||||||
|
Solo dalla pagina del profilo si possono poi aprire le <strong>impostazioni</strong> dell'account, che sono <strong>mischiate</strong> a quelle di amministrazione d'istanza senza netta divisione.<sup id="fnref1"><a class="footnote-ref" href="#fn1">1</a></sup><br>
|
||||||
|
Sulla schermata principale <strong>non tutte le sottosezioni</strong> (tra cui viste specifiche per i flussi di messaggi) sono <strong>visibili</strong>, bisogna cliccare un tasto per mostrare tutti i bottoni.<br>
|
||||||
|
Scelte discutibili.</p>
|
||||||
|
|
||||||
|
<p>Non pare affatto questo l'intento, ma <strong>mi piace pensare</strong> che questo sia un <strong>punto a favore</strong>, perché esegue una <strong>selezione artificiale</strong> degli utenti: quei profughi di Twitter, che mesi fa (ora la situazione si è calmata) arrivavano su Mastodon a comportarsi male - pubblicando messaggi pubblici come "<em>ooo ma come cazzo si usa sto coso?</em>", o "<em>ma che social di merda non si capisce un cazzo</em>", e non riporto altro - non cercheranno rifugio nemmeno per sbaglio da ciò che è "più di un cane" (questa l'etimologia del nome della piattaforma, <a href="https://en.m.wikipedia.org/wiki/Epicyon" rel="noopener nofollow" target="_blank">secondo Wikipedia</a>).</p>
|
||||||
|
|
||||||
|
<h3>Personalizzazione grafica</h3>
|
||||||
|
|
||||||
|
<p>Una delle cose che cercavo più ardentemente nelle impostazioni era la configurazione relativa ai <strong>temi</strong>.<br>
|
||||||
|
Inizialmente scovo solo le opzioni di <strong>personalizzazione di colori</strong> e grandezza del testo del tema applicato, ma per fortuna non era tutto: era un po' nascosta, ma alla fine ho individuato l'opzione <strong>per passare ad un template</strong> completamente diverso.</p>
|
||||||
|
|
||||||
|
<p>Il tema predefinito, infatti, non mi piaceva granché, ma ne ho trovati <strong>alcuni gradevoli</strong> tra quegli altri già inclusi. Il mio <strong>preferito</strong> si chiama "<strong>Pixel</strong>", ed offre una vista che mi appare <strong>rilassante</strong>, con i suoi sfondi di un <strong>violetto pseudo-lavanda</strong> (<code class="prettyprint" style="Background: #9ba0d4; Color:#000000;">#9ba0d4</code>) ed il testo mostrato con un <strong>font particolare</strong>, con caratteri formati da quadratini messi assieme (appunto, a simulare dei pixel chiaramente visibili). L'effetto che fa è <strong>interessante</strong>, perché è evidentemente un tema non classificabile né come chiaro, né come scuro; esiste nella sua categoria. O forse lo si può definire chiaro, perché il testo è nero, allora lo sfondo è necessariamente chiaro per contrasto. Vabbè, non me ne frega: il punto fondamentale è che, per me, è <strong>davvero bello</strong>.</p>
|
||||||
|
|
||||||
|
<p><img src="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/Theme-Designer-Pixel.png" alt="Lo strumento di personalizzazione del tema ("Theme Designer"), visto con caricato il tema "Pixel"."></p>
|
||||||
|
|
||||||
|
<p>Un altro tema che ha attirato la mia attenzione è stato "LCD", che simula un vecchio schermo LCD monocromatico a <strong>sfondo verdognolo</strong>. Lo <strong>apprezzo</strong> molto <strong>a livello artistico</strong>, ma proprio non riesco ad usarlo, è <strong>troppo pesante</strong> sugli occhi usando uno schermo retroilluminato moderno!</p>
|
||||||
|
|
||||||
|
<p>È un <strong>peccato</strong> comunque, secondo me, che le <strong>modifiche</strong> alla grafica siano applicate a livello d'istanza, e quindi <strong>riservate</strong> solo <strong>agli amministratori</strong> (a chi ha il rango "Artist", precisamente). Altre piattaforme, ad esempio Friendica e Misskey, implementano i temi in modo più flessibile.</p>
|
||||||
|
|
||||||
|
<h3>Problemi di scaling</h3>
|
||||||
|
|
||||||
|
<p>Ci sono anche temi più adatti a chiunque, ma purtroppo la grafica del<strong>l'interfaccia</strong> ha un problema anche più grave di cosa può rientrare in desideri estetici non soddisfacibili: <strong>scala male</strong>.<br>
|
||||||
|
Forse con alcuni dei temi il problema non si sente troppo, ma con altri il <strong>testo</strong> è spesso <strong>troppo grande</strong>, e capita diverse volte che <strong>bottoni o icone</strong> siano <strong>sproporzionati</strong> o per giunta disallineati.</p>
|
||||||
|
|
||||||
|
<p>Testando a schermo quasi intero (va quindi tenuto conto dello spazio a schermo occupato da elementi di browser e sistema operativo), su PC desktop con monitor 1360x768, e su mobile con display 9:18 da 6.2", penso che <strong>vorrei</strong> magari un po' <strong>meno</strong> di <strong>padding</strong>, anche se tutto sommato l'interfaccia è OK. L'<strong>inutilizzabilità</strong> arriva quando si tentano risoluzioni un po' più quadrate, ad esempio tenendo la finestra del browser non totalmente allargata in orizzontale sul mio monitor 16:9. In questo caso... beh, lascio parlare il video che segue. Anche sul mio smartphone possono uscire brutture, se lo giro in orizzontale.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<video title="Video che mostra lo scaling a diverse risoluzioni, e come sia troppo storto con alcune, con il tema "Pixel"." class="Center" src="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/UI-Scaling-Bug-Pixel.webm" [:videoelemargs-controlmuteloopauto:]="">Video che mostra lo scaling a diverse risoluzioni, e come sia troppo storto con alcune, con il tema "Pixel".</video>
|
||||||
|
|
||||||
|
<h2>Entrando nel vivo</h2>
|
||||||
|
|
||||||
|
<p>Credo che sarebbe facile per me aggiustare l'interfaccia, visto che si tratterebbe di modificare un po' il CSS e fine della storia.<br>
|
||||||
|
Prima che potessi anche solo pensarci, purtroppo, sono usciti però fuori altri <strong>problemi</strong>, stavolta <strong>di funzionalità</strong>.</p>
|
||||||
|
|
||||||
|
<h3>Provando a pubblicare...</h3>
|
||||||
|
|
||||||
|
<p><strong>Il primissimo post</strong> che ho inviato dalla piattaforma, fatto senza toccare alcuna opzione oltre al semplice campo di testo, <strong>sembrava a posto</strong>.</p>
|
||||||
|
|
||||||
|
<p>Un attimo dopo, appena creato il secondo account, <strong>ho notato</strong> una funzione apprezzabile - che Mastodon ha introdotto solo qualche mese fa, mentre altre piattaforme popolari non presentano proprio: <strong>la scelta della lingua</strong> usata nel proprio post, utilizzata per permettere agli altri utenti di <strong>filtrare</strong> via i messaggi pubblici che appaiono in lingue non desiderate. Ho quindi <strong>impostato</strong> il mio nuovo messaggio <strong>in italiano</strong>, giusto per, ho pubblicato... ed il messaggio <strong>non mi appariva</strong> in alcuna timeline. Solo su Epicyon, però, e da entrambi i miei account; sulle altre istanze appariva normalmente.<br>
|
||||||
|
Ci ho messo 10 minuti buoni a capire che no, non si era appena rotto il mio account, ma banalmente <strong>non posso</strong> vedere nemmeno i miei stessi messaggi se pubblicati in una <strong>lingua non presente nella lista</strong> di quelle da me accettate, che di default è solo inglese. Ho dovuto <strong>a mano</strong> aggiungere almeno l'italiano (ho aggiunto tutte le lingue, già che c'ero) nella lista bianca.<br>
|
||||||
|
Sicuramente è una <strong>svista di programmazione</strong>, perché questo comportamento non avrebbe il minimo senso dal punto di vista della progettazione dell'esperienza utente... però <strong>non va mica bene!</strong></p>
|
||||||
|
|
||||||
|
<p>Comunque, le proprie <strong>pubblicazioni</strong> sono <strong>modificabili</strong>, ottima cosa. Anche qui siamo al pari di Mastodon, ma <strong>al di sopra</strong> di altre piattaforme federate.</p>
|
||||||
|
|
||||||
|
<h3>I flussi di messaggi principali</h3>
|
||||||
|
|
||||||
|
<p>Alcuni punti possono essere dei pro e dei contro, a seconda dei punti di vista.</p>
|
||||||
|
|
||||||
|
<p>L'<strong>assenza</strong> di una <strong>timeline federata</strong> è una cosa un po' scomoda, perché rende la scoperta di nuovi contenuti più difficile, ma non è la fine del mondo: come su altri servizi, <strong>nella home</strong> (che qui si chiama "<strong>Inbox</strong>") <strong>arrivano</strong> le condivisioni di <strong>messaggi di utenti sconosciuti</strong> per mano degli utenti che invece si seguono, quindi ogni tanto <strong>si possono scoprire</strong> nuovi profili da lì.<br>
|
||||||
|
Allo stesso tempo, però, <strong>il server non rischia</strong> di doversi col tempo trovare a fare i conti con <strong>quantità ingestibili di traffico</strong> dati, che saranno invece proporzionali solo all'attività degli utenti sull'istanza e di quelli direttamente seguiti da questi.</p>
|
||||||
|
|
||||||
|
<p>La <strong>mancanza di una cronologia locale</strong>, però, probabilmente si sentirà se si vuole ospitare un server per un proprio gruppo di amici. Mah, forse nemmeno troppo: Epicyon sembra essere pensato per <strong>avere pochi utenti locali</strong> attivi, una dozzina al massimo, e a quel punto ci si segue semplicemente tutti a vicenda.</p>
|
||||||
|
|
||||||
|
<p><img src="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/Timeline-Pixel.png" alt="Una parte della cronologia home, vista su smartphone con il tema "Pixel"."></p>
|
||||||
|
|
||||||
|
<h3>Le ottime prestazioni</h3>
|
||||||
|
|
||||||
|
<p>L'<strong>idea</strong> di far girare un programma di questo tipo <strong>senza</strong> alcun sistema di <strong>database</strong> centralizzato, facendogli memorizzare invece tutti i dati come file sparsi nel file system del sistema, <strong>piace</strong> concettualmente molto anche a me, ma ha dei <strong>limiti di scalabilità</strong> concreti.<br>
|
||||||
|
Chissà che succederebbe se provassi a mettere in piedi un progetto del tipo di "Epicyon<strong>.uno</strong>" o "Epicyon<strong>.social</strong>"... immagino l'immane disastro.</p>
|
||||||
|
|
||||||
|
<p>Però, di base, quando non portato allo stremo, questo software <strong>performa</strong> davvero <strong>come promesso</strong>.<br>
|
||||||
|
Con <strong>htop</strong> possiamo entrare nei dettagli: sul mio <strong><a href="https://web.archive.org/web/20211120100907/https://www.alliedelec.com/m/d/4252b1ecd92888dbb9d8a39b536e7bf2.pdf" rel="noopener nofollow" target="_blank">Raspberry Pi 3</a></strong>, in momenti di <strong>quasi-stallo</strong> (in cui non sto usando l'applicazione, ma il server ha evidentemente dei compiti da svolgere), l'utilizzo <strong>CPU</strong> si aggira attorno al <strong>3%</strong> (su un massimo totale teorico di 400%, considerando i 4 core), e la <strong>RAM</strong> utilizzata tra i <strong>40 e i 70 MB</strong> (circa dal 4.5 al 7.5 % della RAM di un Pi3). L'HTML generato dal server, poi, è essenziale, e il client impiega quindi giusto <strong>qualche istante</strong> per riceverlo.</p>
|
||||||
|
|
||||||
|
<p>Il software non aveva promesso di non avere bug terrificanti, quindi in effetti su quello non ci si può lamentare, ma <strong>quelle poche promesse</strong> che ha fatto <strong>le ha mantenute</strong> benissimo. Oddio, il programma a dirla tutta si dichiara essere <a href="https://gitlab.com/bashrc2/epicyon/-/blob/66203c6558a1bb4fa2a405c45e84f786b606b499/epicyon.py#L7" rel="noopener nofollow" target="_blank">in stato "Production/Stable"</a>, per cui questa scusa regge fino a un certo punto...</p>
|
||||||
|
|
||||||
|
<h3>Reazioni ai post</h3>
|
||||||
|
|
||||||
|
<p>Le cose buone, per fortuna, non finiscono mica qui!<br>
|
||||||
|
Ho con piacere subito notato che la piattaforma permette di <strong>reagire ai messaggi</strong> usando <strong>emoji</strong>, oltre a permettere il classico invio di un apprezzamento per il post - il "mi piace" standard, per intenderci, che qui è un cuore.</p>
|
||||||
|
|
||||||
|
<p><img src="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/React-LCD.png" alt="Schermata di selezione di una reazione ad un messaggio (vista con il tema "LCD")."></p>
|
||||||
|
|
||||||
|
<p>Purtroppo, la <strong>separazione</strong> delle reazioni dall'apprezzamento è decisamente <strong>poco intelligente</strong>.<br>
|
||||||
|
Questo parere non è solo mio, ma anche degli sviluppatori di Misskey e, credo (non ho mai verificato di persona) anche Pleroma: il reagire da lì ad un messaggio proveniente da una piattaforma che non supporta le reazioni (come Mastodon) si traduce in un apprezzamento ricevuto da quell'altro server. Su Epicyon, invece, <strong>reagire</strong> ad una pubblicazione che viene da istanze meno ricche di funzionalità <strong>è virtualmente inutile</strong>.<br>
|
||||||
|
In cima a tutto ciò, non mi pare ci sia nemmeno un modo per consultare un elenco di tutti i messaggi a cui si ha reagito; per cui, <strong>addio all'idea</strong> di usare le <strong>reazioni</strong> almeno <strong>come filtro</strong> personale dei post letti e graditi nel tempo.</p>
|
||||||
|
|
||||||
|
<h3>La ricerca</h3>
|
||||||
|
|
||||||
|
<p>Nel ritrovare pubblicazioni altrui tramite l'interfaccia della piattaforma, abbiamo giusto <strong>qualche limitazione in meno</strong> rispetto a cosa si vede su Mastodon.<br>
|
||||||
|
La <strong>ricerca nel testo</strong> con parole chiave normali è purtroppo limitata ai propri messaggi, ma ci sono altre opzioni per le altre situazioni: oltre a poter <strong>cercare per hashtag</strong> (che, tralaltro, l'interfaccia di ricerca consiglia), a quanto pare si può cercare addirittura <strong>per emoji</strong>! Non ho però testato quest'ulteriore funzione, avendola notata solo troppo tardi.<br>
|
||||||
|
Infine, si possono <strong>cercare elementi</strong> relativi alle funzioni <strong>di economia</strong> della condivisione (a cui ora arrivo): abilità, oppure oggetti e servizi.</p>
|
||||||
|
|
||||||
|
<p><img src="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/Search-Pixel.png" alt="La schermata per iniziare una ricerca (vista dal tema "Pixel")."></p>
|
||||||
|
|
||||||
|
<h2>Le caratteristiche avanzate</h2>
|
||||||
|
|
||||||
|
<p>Da Epicyon, continuando, ci sono <strong>diverse modalità</strong> che si possono impostare per un <strong>messaggio</strong>. Non serve spiegare quelle in comune con le piattaforme maggiori, ma alcune meritano un occhio di riguardo.</p>
|
||||||
|
|
||||||
|
<h3>Economia collaborativa</h3>
|
||||||
|
|
||||||
|
<p>Uno dei punti cardine di Epicyon, almeno questa sarebbe l'idea, è costituito dalle sue funzionalità orientate alla cosiddetta "<a href="https://it.wikipedia.org/wiki/Economia_collaborativa" rel="noopener nofollow" target="_blank">economia della condivisione</a>".<br>
|
||||||
|
È possibile creare post che descrivono <strong>oggetti o servizi</strong>, che si sta <strong>cercando</strong> oppure si sta <strong>mettendo a disposizione</strong>, specificando la relativa <strong>categoria</strong> e (opzionalmente) un <strong>prezzo</strong>.<br>
|
||||||
|
Questi messaggi possono apparire nelle <strong>timeline</strong> a loro <strong>dedicate</strong>, e di default non sono federati; l'admin del server può specificare una lista di istanze terze con le quali federare questo tipo di post.<br>
|
||||||
|
Sul proprio profilo, poi, si può indicare una <strong>lista di</strong> proprie <strong>abilità</strong> (<em>skill</em>), con un livello percentuale.</p>
|
||||||
|
|
||||||
|
<p>Purtroppo - e qui ormai si inizia a notare una tendenza, con i malfunzionamenti - a me pubblicare la <strong>richiesta</strong> di qualcosa <strong>ha funzionato</strong>, mentre provare a postare un'<strong>offerta</strong> (come nuovo messaggio, non correlato al precedente) <strong>non sortito effetti</strong>. Ci ho provato 2 volte ma, proprio no, il nuovo post non compariva.</p>
|
||||||
|
|
||||||
|
<h3>Miscuglio di modalità</h3>
|
||||||
|
|
||||||
|
<p><strong>Mannaggia</strong>, perché anche qui è stata fatta un'indigesta <strong>insalata</strong>: quelle che sono <strong>modalità</strong> definibili come "di ricezione", cioè che determinano a chi il messaggio arriverà e come verrà visualizzato - pubblico, non in elenco, solo-seguaci, o diretto - sono <strong>mischiate</strong> alle modalità che posso definire "di tipologia", cioè che impostano il post come normale (contenente testo e/o file allegati), o come di una categoria speciale.</p>
|
||||||
|
|
||||||
|
<p><img src="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/Post-Modes-Pixel.png" alt="Schermata di pubblicazione, con il menu di selezione di modalità aperto (vista con il tema "Pixel")."></p>
|
||||||
|
|
||||||
|
<p>Nella pratica, questo vuol dire che <strong>non</strong> si può <strong>cambiare</strong> il livello di <strong>privacy</strong> di quei post di tipo <strong>speciale</strong>.<br>
|
||||||
|
Se questa cosa non è magari un problema per le funzioni di <em>sharing economy</em>, che non piazzano nemmeno elementi sulla pagina del profilo utente, può esserlo invece per i sondaggi, purtroppo implementati come tipo di post e non come opzione aggiuntiva per i normali.</p>
|
||||||
|
|
||||||
|
<h3>Problemi coi sondaggi</h3>
|
||||||
|
|
||||||
|
<p>Il fatto che debbano essere per forza pubblici non è la cosa più <strong>bizzarra</strong> dell'<strong>implementazione dei sondaggi</strong>, perché c'è di peggio.</p>
|
||||||
|
|
||||||
|
<p>Pare che <strong>selezionare</strong> (con i bottoncini dedicati, ovviamente) una delle <strong>opzioni</strong> disponibili, per poi premere salva, non sortisca nel backend lo stesso effetto che le altre piattaforme presentano; si <strong>va a creare un commento</strong> di risposta (visibile come tale da altri server), come se a mano si fosse scritta l'opzione desiderata in un nuovo messaggio sotto la stessa discussione.<br>
|
||||||
|
Non solo questo manda in vacca l'anonimità dei sondaggi come previsti da tutte le altre applicazioni, ma <strong>non funziona</strong> e basta: ai contatori dei voti sul sondaggio non viene sommata quella strana risposta.</p>
|
||||||
|
|
||||||
|
<p><img src="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/Polls-Bug.png" alt="Un sondaggio creato da Epicyon, votato e mostrato sia da Epicyon che da Mastodon. Notare il problema descritto."></p>
|
||||||
|
|
||||||
|
<h3>Sguardo agli eventi</h3>
|
||||||
|
|
||||||
|
<p>Ad ogni modo, per qualsiasi tipo di pubblicazione si possono opzionalmente <strong>impostare una posizione</strong> (inserendo un link di OpenStreetMap - cosa che a me non ha funzionato per nulla) <strong>ed una data</strong>, entrambe cose potenzialmente utili se si vuole segnalare un <strong>evento</strong>, qualcosa che Epicyon prevede.</p>
|
||||||
|
|
||||||
|
<p>I post con data dovrebbero manifestarsi anche nella <strong>sezione calendario</strong> dell'app. Non ho verificato se almeno questa cosa funzionasse, purtroppo, ma ho provato il messaggio "<strong>promemoria</strong>", e va: un messaggio di questa tipologia <strong>arriva</strong> dal proprio account, come <strong>diretto</strong>, all'orario stabilito; oltre a comparire nel calendario, è accessibile in un <strong>bottone</strong> (<strong>evidenziato</strong> con un colore alternativo) che appare nella barra di navigazione in cima alla home.</p>
|
||||||
|
|
||||||
|
<p><img src="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/Reminder-Pixel.png" alt="La schermata che mostra un promemoria scattato (vista con il tema "Pixel")."></p>
|
||||||
|
|
||||||
|
<h3>Blogging non-micro</h3>
|
||||||
|
|
||||||
|
<p>L'ultima modalità impostabile per i post è quella di "<strong>articolo</strong>", quindi aventi un <strong>titolo e nessun limite</strong> stretto <strong>per il corpo</strong>; qualcosa di previsto da ActivityPub, adatto al blogging più classico, e che già si osserva in giro da tempo con WriteFreely, Plume, Lemmy, o Friendica.</p>
|
||||||
|
|
||||||
|
<p>Gli articoli dovrebbero finire sulla pagina del proprio profilo... ma a me non succede. La <strong>funzionalità</strong> è <strong>rotta</strong> e l'<strong>unico modo</strong> per trovare gli articoli, propri o degli altri utenti d'istanza, è di <strong>passare per la timeline</strong> dedicata.<br>
|
||||||
|
Ah, <strong>oltre a questa</strong> qui, che è effettivamente una <strong>linea del tempo</strong> a visualizzazione speciale, ce n'è anche <strong>una</strong> che mette in <strong>mostra solo i messaggi multimediali</strong>, un po' come se fosse Pixelfed.</p>
|
||||||
|
|
||||||
|
<h3>Contenuti a livello d'istanza</h3>
|
||||||
|
|
||||||
|
<p>Queste visualizzazioni speciali qui possono, tra l'altro, essere impostate come <strong>modalità dell'istanza</strong>, in un modo che rende possibile la <strong>navigazione dei post</strong> locali <strong>a chi visita il sito</strong> senza fare login.</p>
|
||||||
|
|
||||||
|
<p>A dire il vero, c'è anche una terza opzione per il tipo di istanza: "<strong>news</strong>". Questa mette in primo piano le <strong>notizie</strong> che arrivano dai <strong>flussi impostati</strong> dagli amministratori del server.<br>
|
||||||
|
Proprio così, in questo senso Epicyon mette a disposizione degli strumenti particolarmente interessanti: le notizie, impostate da fonti <strong>RSS</strong>, appaiono in una <strong>barra laterale</strong> su desktop. In base ad un'ulteriore configurazione possono essere soggette a <strong>filtri</strong>, che aggiungono in automatico <strong>hashtag</strong> oppure <strong>avvisi</strong> sui contenuti (<em>content warnings</em>) in base al testo.<br>
|
||||||
|
Il server espone, inoltre, un feed che aggrega tutte le notizie che man mano scarica.</p>
|
||||||
|
|
||||||
|
<p>Dal lato opposto, sempre su desktop, figura infine un'<strong>ulteriore barra</strong>, che mette invece a comoda disposizione dei <strong>link esterni</strong>. Alcuni <strong>riportano</strong> ad informazioni o documentazione dell'istanza, mentre altri possono essere impostati dagli amministratori e puntare <strong>a qualunque URL</strong>. </p>
|
||||||
|
|
||||||
|
<p><img src="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/Featured-LCD.png" alt="La schermata "Featured", che appare selezionabile da un bottone dedicato nella barra di navigazione quando l'istanza è impostata in modalità "news" (vista dal tema "LCD"). Al centro compare il flusso di articoli scritti dai membri del server."></p>
|
||||||
|
|
||||||
|
<h2>Vagonata di casini!</h2>
|
||||||
|
|
||||||
|
<p>Fino a qui, tutto sommato, questo pezzo di software <strong>non sembrava</strong> affatto <strong>malvagio</strong>: con qualche piccolo inconveniente, certo, ma nessun programma più complesso di un <em>Hello World</em> potrà mai essere perfetto, e questo Epicyon ha comunque dei <strong>solidi punti a suo favore</strong>.<br>
|
||||||
|
Il problema, il grosso casino, è che quelle <strong>rogne</strong> serie che <strong>ci sono</strong> sono enormi. Oserei dire <strong>mastodontiche</strong>, per una piattaforma il cui animale è si grosso, ma non elefantiaco!</p>
|
||||||
|
|
||||||
|
<p>Qui non c'è molto spazio per discutere, quindi preferisco fare una <strong>carrellata</strong> veloce.<br>
|
||||||
|
Qualcosa a riguardo di buona parte di questi errori usciva nei <strong>log</strong> del server, ma in modo <strong>troppo generico</strong>, e quindi (anche se pure io non è che ho voluto perderci troppo tempo) non sono riuscita a decifrare il perché certi determinati problemi si verificassero.</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><p>Dopo qualche minuto dal loro invio, <strong>alcuni</strong> dei propri <strong>messaggi possono casualmente sparire dall'istanza</strong>. Non si trovano più navigando in giro, raggiungerli direttamente da link restituisce un errore 404, ma <strong>sulle istanze terze</strong> che li hanno ricevuti in tempo <strong>rimangono</strong> visibili. In modo simile, alcuni messaggi possono sparire dalla pagina del profilo di un altro utente che è locale all'istanza, quando si va a cercarli.</p></li>
|
||||||
|
<li><p>Per la legge del contrappasso, <strong>alcuni messaggi appaiono</strong> come <strong>duplicati</strong> in certe situazioni. Ho osservato che succede sicuramente per i post sulla pagina del proprio profilo (<a href="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/Self-Profile-Pixel.png" rel="noopener nofollow" target="_blank">immagine qui 🖼️</a>), dove addirittura <strong>si sdoppiano a gruppetti</strong>, ma potenzialmente anche per <strong>qualsiasi post</strong> sulla timeline personale <strong>se si fa qualche azione</strong> come <em>boostare</em>.</p></li>
|
||||||
|
<li><p>Parlando di <strong>interazioni</strong> ai post, ho visto che a volte <strong>possono non andare a segno</strong>. Ricordo perfettamente che può succedere con la funzione di <strong>reazione</strong> - in un caso <strong>dovetti riprovare</strong> una seconda volta ad assegnarne una ad un messaggio perché l'azione funzionasse - e mi sembra possa accadere anche con cuore e ricondivisione, ma non ho inquadrato bene questi due casi.</p></li>
|
||||||
|
<li><p>Rimanendo sulle interazioni, stavolta con i profili: è tragico che <em>in alcuni casi</em>* il <strong>tentare di seguire</strong> alcuni account <strong>non funziona</strong> proprio. Premendo su "Follow", qualche volta ho dovuto <strong>aspettare</strong> qualche <strong>decina di secondi</strong> perché l'utente uscisse davvero nella mia lista di seguiti, senza alcuna indicazione da parte dell'applicazione; <strong>altre volte</strong>, addirittura, anche <strong>aspettare</strong> ore (giorni...) o riprovare più volte <strong>non è servito</strong> a nulla. Pare che il problema non dipenda dal software su cui gira l'istanza remota, quindi non ho la minima idea del perché succeda.</p></li>
|
||||||
|
<li><p>Ci sono <strong>due pagine diverse</strong> che possono apparire <strong>per i profili</strong>: una con la vista dei post recenti (di cui ho linkato una schermata poco sopra), ma nessuna opzione a parte il seguire, e una con diverse opzioni (di cui lascio un'<a href="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/Profile-Options-Pixel.png" rel="noopener nofollow" target="_blank">immagine qui 🖼️</a>). <strong>A volte si apre la prima, altre la seconda.</strong> Non centra la parte dell'applicazione da cui si proviene per aprire la schermata, e non vedo alcun modo per passare da una sezione all'altra. La seconda sembra uscire più comunemente quando si segue già l'account che si sta vedendo, ma non sempre. <strong>Se si vuol vedere i messaggi</strong> in particolare di un utente, <strong>ma il software ha deciso di no</strong> in quel momento, in pratica, <strong>ci si attacca</strong>.</p></li>
|
||||||
|
<li><p>Bug veramente singolare: <strong>gli account di Misskey appaiono con un ID alfanumerico al posto del normale username</strong> (solo la prima parte - quella che invece indica il dominio è a posto). Non ci sono problemi se si prova a riferirsi ad un account con il suo vero username, perché il messaggio arriva (o la ricerca va a segno, se è quella funzione che si sta usando)... però, <strong>se si sta rispondendo</strong> all'account in questione, <strong>l'username suggerito sarà quello</strong> strano, <strong>che</strong> non esiste e quindi <strong>non funziona</strong>. Anche se non rompesse i messaggi, questo problema sarebbe comunque fastidioso, perché non permetterebbe di capire a colpo d'occhio con chi si sta parlando... immagino già come sarebbe partecipare a thread con tanti utenti.<br>
|
||||||
|
<img src="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/Misskey-ID-Bug.png" alt="Un utente Misskey, visualizzato su Epicyon con foto di profilo, nome, e descrizione corretti (qui censurati), ma username preso dal nulla ("@91f967c3pb@misskey.social")."></p></li>
|
||||||
|
<li><p>Alcune <strong>impostazioni</strong> dell'istanza sono <strong>senzienti</strong> e <strong>cambiano stato da sole</strong>. A volte ad esempio, dopo un riavvio del server, <strong>l'opzione che apre</strong> le <strong>nuove registrazioni</strong> a chiunque <strong>si riattiva</strong> da sola. Qualcosa è successo anche riguardo la modalità dell'istanza, che è passata da standard a "news" senza che io la impostassi così; questo però potrebbe non essere un bug, magari qualche azione che ho fatto come admin (e che non ricordo, ecco qua) ha avuto questo effetto collaterale ma previsto dagli sviluppatori. Non lo sapremo mai, ma è una cosa che <strong>fa spavento</strong>.</p></li>
|
||||||
|
<li><p>C'è qualche <strong>problema con il reperimento</strong>, e/o eccessività di caching, <strong>dei metadati degli account da parte di istanze terze</strong>. Ho controllato da diversi altri server, facendo alcuni test che mi portano ad alcune <em>conclusioni inconcludenti</em>; in particolare, <strong>riguardo le foto di profilo</strong> (la principale quadrata):</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Mastodon, ho provato diverse istanze, si rifiuta completamente di vedere la <em>fotina</em>, e al suo posto mette il segnaposto elefantiaco.</li>
|
||||||
|
<li>Misskey va così e così: alcune istanze mettono il loro segnaposto, mentre altre caricano come immagine di profilo la foto del banner (che però non ho mai impostato, e quindi vedo che Epicyon ne mette da solo una in base al tema d'istanza; bella sorpresa!)... non mi porrò domande, va.</li>
|
||||||
|
<li>Friendica (di cui solo un'istanza ho potuto usare), invece, riesce a vedere la foto. Friendica però è un software un attimo più avanzato, ed internamente usa ricorrere a metodi articolati per ottenere i metadati di tanti tipi di risorse Web.
|
||||||
|
Tutto sommato, potrebbe essere un <strong>problema di caching</strong> (chissà se dal lato del mio server, o degli altri), e magari non di dati malformati, ma resta una roba che <strong>non funziona</strong>.</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2>E adesso?</h2>
|
||||||
|
|
||||||
|
<p>Il <strong>sogno</strong> di un <strong>server</strong> ActivityPub <strong>leggero ma ricco</strong> di funzioni è inesorabilmente <strong>crollato</strong>, non c'è veramente altro da poter dire. Dopo aver visto appena soltanto i primi problemini <strong>pensavo di voler tenere Epicyon</strong> per almeno una settimana, così da testarlo per bene, <strong>ma</strong> alla fine ha iniziato a comportarsi troppo male. <strong>Ho dovuto farlo fuori</strong> dopo appena 2 giorni.<br>
|
||||||
|
È davvero <strong>un peccato</strong>, allora, che si sia dimostrato <strong>troppo scassato</strong> per essere realisticamente utilizzabile. Per ora devo quindi optare per altri software, e forse qualcosa di buono l'ho trovato - e questa è una storia per una prossima volta - ma <strong>spero</strong> davvero <strong>che Epicyon possa</strong> in futuro <strong>diventare utilizzabile</strong>.</p>
|
||||||
|
|
||||||
|
<p><strong>Fortunatamente</strong>, anche se per mano di una sola persona, quindi lentamente, <strong>lo sviluppo va avanti</strong> ad un ritmo di <a href="https://gitlab.com/bashrc2/epicyon/activity" rel="noopener nofollow" target="_blank">diversi commit al giorno</a>.<br>
|
||||||
|
A proposito di ciò, dopo aver fatto una <strong>guardata tocca e fuggi</strong> ai sorgenti, una cosa devo dirla: in confronto ai server più affermati, <strong>il codice</strong> di questo qui <strong>mi sembra messo</strong> parecchio <strong>male</strong>. I file non sono ben suddivisi in cartelle, ce ne sono alcuni che arrivano a centinaia (o persino <a href="https://gitlab.com/bashrc2/epicyon/-/blob/66203c6558a1bb4fa2a405c45e84f786b606b499/daemon.py" rel="noopener nofollow" target="_blank">un migliaio!</a>) di kilobyte, e ci sono funzioni enormi in cui figurano loop e controlli sotto tanti, troppi livelli di indentazione.<br>
|
||||||
|
Non vorrei essere nei panni di colui che lo sta mantenendo perché, per come stanno le cose, temo che <strong>sistemare questo software</strong> per farlo funzionare a dovere <strong>non sarà una cosa semplice</strong>, e non prenderà affatto poco tempo...</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2>[:HNotesRefsHTML:]</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="footnotes">
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
<li id="fn1">
|
||||||
|
<p>Guardare <strong>tutte le impostazioni disponibili</strong> può dare una buona visione su quali sono alcune delle potenzialità di una qualsiasi piattaforma. Commentarle tutte, specialmente quelle che non ho testato, sarebbe follia; ho però pensato di lasciare <a href="[staticoso:CustomPath:Assets]/Media/Epicyon-Dec-2022/Settings.png" rel="noopener nofollow" target="_blank">qui una schermata 🖼️</a> completa, chi vuole può almeno leggere le varie opzioni per conto proprio. <a href="#fnref1">↩</a></p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ol>
|
||||||
|
</div>
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
# Lista di Tutti i Post
|
# Lista di Tutti i Post
|
||||||
|
|
||||||
|
_Quelli più in alto alla lista sono i più recenti!_
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<staticoso:DirectoryList:Posts/>
|
<staticoso:DirectoryList:Posts/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,7 +7,7 @@ const BlogURL = 'https://listed.to/@u8'; // Full base URL of the Listed blog (an
|
||||||
const SiteName = 'sitoctt';
|
const SiteName = 'sitoctt';
|
||||||
//const DefaultMode = 'Include' // 'Include' or 'Exclude' | Not implemented
|
//const DefaultMode = 'Include' // 'Include' or 'Exclude' | Not implemented
|
||||||
const PostsFileDate = true; // Append dates (YYYY-MM-DD) to posts file names
|
const PostsFileDate = true; // Append dates (YYYY-MM-DD) to posts file names
|
||||||
const Replacements = { // Format: { ReplaceWithString: [ToFindString] }
|
let Replacements = { // Format: { ReplaceWithString: [ToFindString] }
|
||||||
"<h2>[:HNotesRefsHTML:]</h2>": "<h2>🏷️ Note e Riferimenti</h2>",
|
"<h2>[:HNotesRefsHTML:]</h2>": "<h2>🏷️ Note e Riferimenti</h2>",
|
||||||
'<div class="footnotes">': ['<div class="footnotes"><hr>', '<div class="footnotes">\n<hr>'],
|
'<div class="footnotes">': ['<div class="footnotes"><hr>', '<div class="footnotes">\n<hr>'],
|
||||||
'"><a class="footnote-ref" href="#fn': '"><a href="#fn',
|
'"><a class="footnote-ref" href="#fn': '"><a href="#fn',
|
||||||
|
@ -15,9 +15,12 @@ const Replacements = { // Format: { ReplaceWithString: [ToFindString] }
|
||||||
" src=\"[staticoso:CustomPath:Assets]/": " src=\"https://sitoctt-assets.octt.eu.org/",
|
" src=\"[staticoso:CustomPath:Assets]/": " src=\"https://sitoctt-assets.octt.eu.org/",
|
||||||
// TODO: Fix anchor rels
|
// TODO: Fix anchor rels
|
||||||
};
|
};
|
||||||
|
const TestURL = 'https://listed.to/p/hDaMhJ2ts7';
|
||||||
|
|
||||||
const MetadataBlockSelect = '.MetadataBlock, .MetadataBlock + :Where(Div, Pre, Code)';
|
const MetadataBlockSelect = '.MetadataBlock, .MetadataBlock + :Where(Div, Pre, Code)';
|
||||||
|
const ReplacementsBlockSelect = '.ReplacementsBlock, .ReplacementsBlock + :Where(Div, Pre, Code)';
|
||||||
const ExtractCodeBlockSelect = '.ExtractCodeBlock, .ExtractCodeBlock + :Where(Div, Pre, Code)';
|
const ExtractCodeBlockSelect = '.ExtractCodeBlock, .ExtractCodeBlock + :Where(Div, Pre, Code)';
|
||||||
|
const DeleteElementBlockSelect = '.DeleteElementBlock';
|
||||||
|
|
||||||
const TryReadFileSync = Path => {
|
const TryReadFileSync = Path => {
|
||||||
if (fs.existsSync(Path)) {
|
if (fs.existsSync(Path)) {
|
||||||
|
@ -44,6 +47,10 @@ const GetFragHTML = Frag => {
|
||||||
return Dom.window.document.body.innerHTML.trim();
|
return Dom.window.document.body.innerHTML.trim();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CSSFirstTokenSelector = Select => {
|
||||||
|
return Select.trim().replaceAll('.', '').replaceAll(',', '').split(' ')[0];
|
||||||
|
};
|
||||||
|
|
||||||
const CheckDownsync = Body => {
|
const CheckDownsync = Body => {
|
||||||
if (Body) {
|
if (Body) {
|
||||||
const Lines = Body.trim().toLowerCase().split('\n');
|
const Lines = Body.trim().toLowerCase().split('\n');
|
||||||
|
@ -124,7 +131,7 @@ const MakeMetaStr = Post => {
|
||||||
return Str;
|
return Str;
|
||||||
};
|
};
|
||||||
|
|
||||||
const HandlePost = PostSrc => {
|
const HandlePost = (PostSrc, Output) => {
|
||||||
let ContentDom, LinkPath;
|
let ContentDom, LinkPath;
|
||||||
let Post = {'Meta': {}, 'Macros': {}};
|
let Post = {'Meta': {}, 'Macros': {}};
|
||||||
|
|
||||||
|
@ -135,7 +142,7 @@ const HandlePost = PostSrc => {
|
||||||
|
|
||||||
ContentDom = JSDOM.fragment(Post.Content);
|
ContentDom = JSDOM.fragment(Post.Content);
|
||||||
|
|
||||||
// Handle MetadataBlock elements
|
// Handle .MetadataBlock elements
|
||||||
let MetadataBlocks = ContentDom.querySelectorAll(MetadataBlockSelect);
|
let MetadataBlocks = ContentDom.querySelectorAll(MetadataBlockSelect);
|
||||||
for (let i=0; i<MetadataBlocks.length; i++) {
|
for (let i=0; i<MetadataBlocks.length; i++) {
|
||||||
const Elem = MetadataBlocks[i];
|
const Elem = MetadataBlocks[i];
|
||||||
|
@ -162,6 +169,24 @@ const HandlePost = PostSrc => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle .ReplacementsBlock elements: Add replacements to do to the default ones or override them.
|
||||||
|
let ReplBlocks = ContentDom.querySelectorAll(ReplacementsBlockSelect);
|
||||||
|
for (let i=0; i<ReplBlocks.length; i++) {
|
||||||
|
const Elem = ReplBlocks[i];
|
||||||
|
let Text = Elem.textContent.trim();
|
||||||
|
if (Text) {
|
||||||
|
if (!(Text.startsWith('{') && Text.endsWith('}'))) {
|
||||||
|
Text = `{${Text}}`;
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
Replacements = Object.assign(Replacements, JSON.parse(Text));
|
||||||
|
} catch(e) {
|
||||||
|
console.log(`[W] : Problem parsing JSON in a ReplacementsBlock; Ignoring!`);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
ReplBlocks[i].outerHTML = '';
|
||||||
|
};
|
||||||
|
|
||||||
Post.Content = GetFragHTML(ContentDom);
|
Post.Content = GetFragHTML(ContentDom);
|
||||||
|
|
||||||
const PathFile = LinkPath.split('/').slice(-1)[0];
|
const PathFile = LinkPath.split('/').slice(-1)[0];
|
||||||
|
@ -189,12 +214,21 @@ const HandlePost = PostSrc => {
|
||||||
|
|
||||||
ContentDom = JSDOM.fragment(Post.Content);
|
ContentDom = JSDOM.fragment(Post.Content);
|
||||||
|
|
||||||
// Handle ExtractCodeBlock elements
|
// Handle .DeleteElementBlock elements: Elements that must be visible on Listed but deleted here.
|
||||||
// TODO: Opposite of extract blocks? (Allowing some HTML to remain on Listed but get deleted from here)
|
let DelElemBlocks = ContentDom.querySelectorAll(DeleteElementBlockSelect);
|
||||||
|
for (let i=0; i<DelElemBlocks.length; i++) {
|
||||||
|
const Elem = DelElemBlocks[i];
|
||||||
|
if (!Elem.textContent) {
|
||||||
|
DelElemBlocks[i].nextElementSibling.outerHTML = '';
|
||||||
|
};
|
||||||
|
DelElemBlocks[i].outerHTML = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle .ExtractCodeBlock elements: Allow for text to be treated as plain on Listed, and then extracted here.
|
||||||
let ExtCodeBlocks = ContentDom.querySelectorAll(ExtractCodeBlockSelect);
|
let ExtCodeBlocks = ContentDom.querySelectorAll(ExtractCodeBlockSelect);
|
||||||
for (let i=0; i<ExtCodeBlocks.length; i++) {
|
for (let i=0; i<ExtCodeBlocks.length; i++) {
|
||||||
const Elem = ExtCodeBlocks[i];
|
const Elem = ExtCodeBlocks[i];
|
||||||
const Find = ExtractCodeBlockSelect.trim().replaceAll('.', '').replaceAll(',', '').split(' ')[0];
|
const Find = CSSFirstTokenSelector(ExtractCodeBlockSelect);
|
||||||
if (Array.from(Elem.classList).includes(Find)) {
|
if (Array.from(Elem.classList).includes(Find)) {
|
||||||
ExtCodeBlocks[i].outerHTML = ''; // Remove the ExtractCodeBlock upper-marker
|
ExtCodeBlocks[i].outerHTML = ''; // Remove the ExtractCodeBlock upper-marker
|
||||||
} else {
|
} else {
|
||||||
|
@ -204,6 +238,7 @@ const HandlePost = PostSrc => {
|
||||||
|
|
||||||
Post.Content = GetFragHTML(ContentDom);
|
Post.Content = GetFragHTML(ContentDom);
|
||||||
|
|
||||||
|
if (Output == 'file') {
|
||||||
TryMkdirSync(PathDir);
|
TryMkdirSync(PathDir);
|
||||||
fs.writeFileSync(FinalFilePath, `\
|
fs.writeFileSync(FinalFilePath, `\
|
||||||
${MakeMetaStr(Post)}
|
${MakeMetaStr(Post)}
|
||||||
|
@ -211,6 +246,9 @@ ${MakeMetaStr(Post)}
|
||||||
|
|
||||||
${Post.Content}
|
${Post.Content}
|
||||||
`);
|
`);
|
||||||
|
} else if (Output == 'stdout') {
|
||||||
|
console.log(Post.Content);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const Main = _ => {
|
const Main = _ => {
|
||||||
|
@ -220,9 +258,19 @@ const Main = _ => {
|
||||||
const Elem = JSDOM.fragment(Data).querySelector('script[data-component-name="AuthorAll"]');
|
const Elem = JSDOM.fragment(Data).querySelector('script[data-component-name="AuthorAll"]');
|
||||||
const Posts = JSON.parse(Elem.childNodes[0].data).posts;
|
const Posts = JSON.parse(Elem.childNodes[0].data).posts;
|
||||||
for (let i=0; i<Posts.length; i++) {
|
for (let i=0; i<Posts.length; i++) {
|
||||||
HandlePost(Posts[i]);
|
HandlePost(Posts[i], 'file');
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Test = _ => {
|
||||||
|
console.log('[I] Testing...');
|
||||||
|
fetch(TestURL).then(Response => Response.text()).then(Data => {
|
||||||
|
const Elem = JSDOM.fragment(Data).querySelector('script[data-component-name="PostShow"]');
|
||||||
|
const Post = JSON.parse(Elem.childNodes[0].data).post;
|
||||||
|
HandlePost(Post, 'stdout');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
Main();
|
Main();
|
||||||
|
//Test();
|
||||||
|
|
|
@ -2,9 +2,13 @@
|
||||||
import hashlib, os, shutil, sys, time
|
import hashlib, os, shutil, sys, time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
GoogleLangs = ['af', 'sq', 'am', 'ar', 'hy', 'as', 'ay', 'az', 'bm', 'eu', 'be', 'bn', 'bho', 'bs', 'bg', 'ca', 'ceb', 'ny', 'zh', 'zh_HANT', 'co', 'hr', 'cs', 'da', 'dv', 'doi', 'nl', 'en', 'eo', 'et', 'ee', 'tl', 'fi', 'fr', 'fy', 'gl', 'ka', 'de', 'el', 'gn', 'gu', 'ht', 'ha', 'haw', 'iw', 'hi', 'hmn', 'hu', 'is', 'ig', 'ilo', 'id', 'ga', 'it', 'ja', 'jw', 'kn', 'kk', 'km', 'rw', 'gom', 'ko', 'kri', 'ku', 'ckb', 'ky', 'lo', 'la', 'lv', 'ln', 'lt', 'lg', 'lb', 'mk', 'mai', 'mg', 'ms', 'ml', 'mt', 'mi', 'mr', 'mni-Mtei', 'lus', 'mn', 'my', 'ne', 'no', 'or', 'om', 'ps', 'fa', 'pl', 'pt', 'pa', 'qu', 'ro', 'ru', 'sm', 'sa', 'gd', 'nso', 'sr', 'st', 'sn', 'sd', 'si', 'sk', 'sl', 'so', 'es', 'su', 'sw', 'sv', 'tg', 'ta', 'tt', 'te', 'th', 'ti', 'ts', 'tr', 'tk', 'ak', 'uk', 'ur', 'ug', 'uz', 'vi', 'cy', 'xh', 'yi', 'yo', 'zu'] # {LingvaURL}/api/v1/languages
|
||||||
|
DeepLLangs = ['et', 'ja', 'lt', 'lv', 'de', 'hu', 'ru', 'zh', 'ro', 'da', 'it', 'es', 'nl', 'fr', 'sk', 'sl', 'pt', 'en', 'sv', 'fi', 'pl', 'el', 'bg', 'cs'] # All from output of `deepl --help`
|
||||||
|
UserAgent = 'sitoctt:Translate.py'
|
||||||
|
|
||||||
Engine = 'Google' # 'Google' or 'DeepL'
|
Engine = 'Google' # 'Google' or 'DeepL'
|
||||||
SourceLang = 'it'
|
SourceLang = 'it'
|
||||||
DestLangs = ['de', 'en', 'es', 'fr', 'it', 'jp', 'ko', 'pt', 'ru', 'zh'] #['et', 'ja', 'lt', 'lv', 'de', 'hu', 'ru', 'zh', 'ro', 'da', 'it', 'es', 'nl', 'fr', 'sk', 'sl', 'pt', 'en', 'sv', 'fi', 'pl', 'el', 'bg', 'cs'] # All from output of `deepl --help`
|
DestLangs = GoogleLangs
|
||||||
|
|
||||||
# With shutil.copytree copy only folder struct, no files; https://stackoverflow.com/a/15664273
|
# With shutil.copytree copy only folder struct, no files; https://stackoverflow.com/a/15664273
|
||||||
def IgnoreFiles(Dir, Files):
|
def IgnoreFiles(Dir, Files):
|
||||||
|
@ -29,7 +33,7 @@ def StrReverse(Str):
|
||||||
def TryTranslate(Text):
|
def TryTranslate(Text):
|
||||||
try:
|
try:
|
||||||
if Engine.lower() == 'google':
|
if Engine.lower() == 'google':
|
||||||
return json.loads(urlopen(Request(f'{LingvaInstance}/api/v1/{SourceLang}/{Lang}/{URLParse.quote(Text, safe="")}')).read())["translation"]
|
return json.loads(urlopen(Request(f'{LingvaURL}/api/v1/{SourceLang}/{Lang}/{URLParse.quote(Text, safe="")}', headers={'User-Agent':UserAgent})).read())["translation"]
|
||||||
elif Engine.lower() == 'deepl':
|
elif Engine.lower() == 'deepl':
|
||||||
return Translate.translate(Text)
|
return Translate.translate(Text)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -37,7 +41,7 @@ def TryTranslate(Text):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if Engine.lower() == 'google':
|
if Engine.lower() == 'google':
|
||||||
LingvaInstance = sys.argv[1]
|
LingvaURL = sys.argv[1]
|
||||||
import json
|
import json
|
||||||
from urllib import parse as URLParse
|
from urllib import parse as URLParse
|
||||||
from urllib.request import urlopen, Request
|
from urllib.request import urlopen, Request
|
||||||
|
|
1
Site.ini
1
Site.ini
|
@ -56,3 +56,4 @@ HTMLTgtBlank = target="_blank" rel="noopener"
|
||||||
MdTgtBlank = " target="_blank" rel="noopener
|
MdTgtBlank = " target="_blank" rel="noopener
|
||||||
MdTgtBlankNofw = " target="_blank" rel="noopener nofollow
|
MdTgtBlankNofw = " target="_blank" rel="noopener nofollow
|
||||||
YouTubeURL = https://invidious.weblibre.org/
|
YouTubeURL = https://invidious.weblibre.org/
|
||||||
|
videoelemargs-controlmuteloopauto = controls="true" muted="true" loop="true" autoplay="true"
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
<!-- Wikipedia | https://commons.wikimedia.org/wiki/File:Wikipedia-microbar-hu.png --->
|
<!-- Wikipedia | https://commons.wikimedia.org/wiki/File:Wikipedia-microbar-hu.png --->
|
||||||
<span><a title="hu:User:Boro, CC BY-SA 3.0 <https://creativecommons.org/licenses/by-sa/3.0>, via Wikimedia Commons" href="https://www.wikipedia.org" target="_blank" rel="noopener nofollow"><img title="Wikipedia" src="<staticoso:CustomPath:Assets>/Media/Buttons/Sites/Wikipedia/Wikipedia-88x31.png"></a><a style="Font-Size:Small; Margin-Left:-2em; Color:Black; Vertical-Align:Super;" title="hu:User:Boro, CC BY-SA 3.0 <https://creativecommons.org/licenses/by-sa/3.0>, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Wikipedia-microbar-hu.png" target="_blank" rel="noopener nofollow">[s]</a></span>
|
<span><a title="hu:User:Boro, CC BY-SA 3.0 <https://creativecommons.org/licenses/by-sa/3.0>, via Wikimedia Commons" href="https://www.wikipedia.org" target="_blank" rel="noopener nofollow"><img title="Wikipedia" src="<staticoso:CustomPath:Assets>/Media/Buttons/Sites/Wikipedia/Wikipedia-88x31.png"></a><a class="YesHoverLight" style="Font-Size:Small; Margin-Left:-2em; Color:Black; Vertical-Align:Super;" title="hu:User:Boro, CC BY-SA 3.0 <https://creativecommons.org/licenses/by-sa/3.0>, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Wikipedia-microbar-hu.png" target="_blank" rel="noopener nofollow">[s]</a></span>
|
||||||
|
|
Loading…
Reference in New Issue