Migracja systemu komentarzy ÔÇö utterances

Migracja systemu komentarzy z Disqus do GitHub Issues z u┼╝yciem Utterances.
Zawarto┼Ť─ç

Odk─ůd zacz─ů┼éem przygody z w┼éasn─ů stron─ů internetow─ů, wa┼╝ne by┼éo, aby nawi─ůza─ç swojego rodzaju kontakt z czytelnikiem. System komentarzy by┼é przy tym niezast─ůpiony.

Zaczynaj─ůc od wbudowanego systemu w Wordpress, kt├│ry szybko zalewany by┼é spamem, przenios┼éem si─Ö na Disqus. Z Disqus zosta┼éem przez ca┼éy okres, w tym przenios┼éem go podczas rezygnacji z WordPress na rzecz Hugo.

Podczas migracji do Hugo, g┼é├│wnym celem by┼é wygl─ůd, kt├│ry zadowoli, mnie jak i czytelnik├│w, ale r├│wnie┼╝ ÔÇô a co najwa┼╝niejsze ÔÇô szybko┼Ť─ç.

Dzi─Öki odpowiednim modyfikacj─ů moja strona ┼éaduj si─Ö szybko, plasuj─ůc si─Ö na zielono w Google PageSpeed czy te┼╝ GTMetrix.

Oczywi┼Ťcie, nie wszystkie elementy strony s─ů zoptymalizowane pod k─ůtem pr─Ödko┼Ťci.

Nie chcia┼éem rezygnowa─ç z systemu reklam bazuj─ůcego na Google AdSense, wi─Öc podstrony, kt├│re wy┼Ťwietlaj─ů reklamy, s─ů nieco wolniejsze od innych. Na to niestety nie mam wp┼éywu.

Na co mam wpływ to system komentarzy.

Disqus nie jest lekki, przez co ograniczy┼éem jego ┼éadowane do czasu, a┼╝ czytelnik zechce zostawi─ç komentarz i kliknie przycisk “Poka┼╝ komentarze”. Pozwoli┼éo mi to zniwelowa─ç negatywny wp┼éyw zasobo┼╝erno┼Ťci Disqus oraz ograniczy┼éo po cz─Ö┼Ťci ┼Ťledzenie u┼╝ytkownik├│w, kt├│re w Disqus jest wszechobecne.

Jako ┼╝e aspekt prywatno┼Ťci jest obecnie na porz─ůdku dziennym, postanowi┼éem sprawdzi─ç, jak─ů alternatyw─Ö mog─Ö wprowadzi─ç na moj─ů stron─Ö, aby raz na zawsze zrezygnowa─ç z Disqus.

Nie zamierza┼éem korzysta─ç z takich opcji, ┼╝e po ka┼╝dym komentarzu moja statyczna strona musi zosta─ç ponownie wygenerowana, aby komentarz by┼é wy┼Ťwietlony. W zwi─ůzku z tym rozpocz─ů┼éem poszukiwania.

Poni┼╝ej opisz─Ö, jak (po stoczonej walce z samym sob─ů) przenios┼éem komentarze z Disqus do GitHub Issues. Jednocze┼Ťnie poni┼╝szy wpis b─Ödzie swojego rodzaju histori─ů zmian na mojej stronie, gdzie zostawi─Ö cz─Ö┼Ť─ç mojego “starego” kodu z Disqus.

Jak Disqus działa(ł) na mojej stronie #

Disqus u┼╝ywa┼éem na mojej stronie w dwojaki spos├│b. Po pierwsze, przywo┼éywa┼éem disqus count.js, kt├│ry wy┼Ťwietla┼é w nag┼é├│wku (i p├│┼║niej w przycisku do ┼éadowania komentarzy) ile dany wpis ma komentarzy, w postaci cyfry.

<script id="dsq-count-scr" src="https://dariuszwieckiewicz.disqus.com/count.js" async></script>
<a href="{{ .Permalink }}#disqus_thread" class="article-comment-link">{{ T "Comments" }} <span class="disqus-comment-count" data-disqus-url="{{ trim .Permalink "/" }}"></span></a>

Nast─Öpnie pod tekstem wpisu mia┼éem przycisk, kt├│ry wy┼Ťwietla┼é liczb─Ö komentarzy i na kt├│rego mo┼╝na by┼éo klikn─ů─ç, aby przywo┼éa─ç disqus embed.js w celu za┼éadowania skryptu i wy┼Ťwietlenia komentarzy zapisanych na serwerach Disqus.

<script>
  var button = document.getElementById("show-comments")
  if (button != null) {

    var clickHandler = function(){
      var disqus_shortname = 'dariuszwieckiewicz';

      var disqus = document.createElement('script');
      disqus.type = 'text/javascript';
      disqus.async = true;
      disqus.src = 'https://' + disqus_shortname + '.disqus.com/embed.js';
      (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(disqus);

      button.style.display = 'none';
  };

  button.addEventListener('click', clickHandler, false);
}
</script>
<div class="disqus-comments">
  <h4>Do┼é─ůcz do dyskusji</h4>
  <button aria-label="{{ T "ShowComments" }}" id="show-comments" class="btn btn-default" type="button"><span class="disqus-comment-count" data-disqus-url="{{ trim .Permalink "/" }}">{{ T "ShowComments" }}</span></button>
  <div id="disqus_thread"></div>

    <script>
      var disqus_config = function () {
        this.page.url = '{{ trim .Permalink "/" }}';
      };
    </script>

</div>

Metod─Ö na przycisk wprowadzi┼éem z prostego wzgl─Ödu, gdy┼╝ nie ka┼╝dy wpis posiada┼é komentarze, a marnowanie czasu na ┼éadowanie skryptu na ka┼╝dej stronie mia┼éo negatywny wp┼éyw na wydajno┼Ť─ç ca┼éej strony.

Eksport komentarzy z Disqus #

Jako że nie chciałem stracić obecnych komentarzy, najpierw musiałem wyeksportować je z Disqus to pliku.

W tym celu zalogowa┼éem si─Ö na moje konto w Disqus, a nast─Öpnie przesz┼éem na stron─Ö administracyjn─ů sk─ůd wybra┼éem moj─ů stron─Ö internetow─ů.

Przechodz─ůc do zak┼éadki Moderation, po lewej stronie mamy dost─Öpne menu Export, w kt├│rym to klikaj─ůc na przycisk Export Comments mo┼╝emy zleci─ç wykonanie kopii zapasowej.

Disqus Moderation Export

Eksport nie nast─Öpuje natychmiastowo, dlatego powita nas wiadomo┼Ť─ç:

Your export has been queued. We will send an email to your registered address when it is available.

W zale┼╝no┼Ťci od tego, jak du┼╝o mamy komentarzy, po chwili (d┼éu┼╝szej lub kr├│tszej) otrzymamy maila, ┼╝e nasz eksport jest gotowy do pobrania, wraz z odno┼Ťnikiem do pobrania pliku XML spakowanego w GZip.

I tak mam plik z komentarzami, który muszę przerobić i z importować do mojego repozytorium na GitHub. W tym celu utworzyłem repozytorium o nazwie mojej strony idarek/dariusz.wieckiewicz.org.

Rozpakowujemy plik i tak otrzymujemy nasz plik XML.

Poszukiwania metody importu komentarzy do GitHub Issues #

W swoich poszukiwaniach natrafi┼éem na dwa przeplataj─ůce si─Ö wpisy, Removing Disqus and adding GitHub Issue Comments) oraz Migrate Disqus comments to Utterances (in GitHub issues) with Python.

Autorzy obu stron przedstawili różne metody na przeniesienie komentarzy. Jürgen wykorzystał .NET, natomiast Pawamoy skrypt w Python.

Chcia┼éem skupi─ç si─Ö na wpisie J├╝rgena, jednak jako u┼╝ytkownika macOS (mimo ┼╝e Windows mam pod r─Ök─ů wirtualnie) nie chcia┼éem u┼╝ywa─ç narz─Ödzia dzia┼éaj─ůcego g┼é├│wnie pod jednym systemem (Windows), mimo dost─Öpnego pakietu .NET na macOS, wi─Öc poszuka┼éem innego rozwi─ůzania. To rozwi─ůzanie znalaz┼éem na stronie pawamoy, kt├│ry wykorzystuje skrypt Python.

Importowanie komentarzy ÔÇö podej┼Ťcie pierwsze #

Rozwi─ůzanie od Pawamoy wyda┼éa┼éo si─Ö prostrze w u┼╝yciu (pozornie).

W pierwszej kolejno┼Ťci nale┼╝a┼éo wygenerowa─ç token dost─Öpowy do GitHub z opcj─ů public_repo.

Generate Token GitHub

Tak wygenerowany token nale┼╝a┼éoby wklei─ç w konfiguracj─Ö parametr├│w ┼Ťrodowiskowych dla dalszego skryptu python. Dostosowa┼éem r├│wnie┼╝ nazw─ů u┼╝ytkownika, repozytorium oraz adres mojej strony.

Wygl─ůda┼éoby to mniej wi─Öcej tak:

export FILEPATH="comments.xml"
export USERNAME="idarek"
export TOKEN="naszWygenerowanyToken"
export REPOSITORY="idarek/dariusz.wieckiewicz.org"
export BASE_URL="https://dariusz.wieckiewicz.org/"

W dalszej cz─Ö┼Ťci nale┼╝a┼éoby skopiowa─ç g┼é├│wny skrypt (nieco go dostosowuj─ůc ÔÇö spolszczaj─ůc) i uruchomi─ç.

Nim to jeszcze zrobiłem, doczytałem i otrzymałem potwierdzenie od autora skryptu, że aby wszystko działało, Utterances musi już działać, a na każdym wpisie, na którym był komentarz w Disqus, należy napisać komentarz testowy, aby Utterance utworzył wstępny GitHub Issue. W przeciwnym razie nie będzie to działać.

Je┼╝eli w przypadku niewielkiej liczby wpis├│w to mo┼╝e nie jest problem, ale wyobra┼║cie sobie robienie tego przy setkach wpis├│w i komentarzy. Pomy┼Ťla┼éem wi─Öc, ┼╝e odpuszcz─Ö.

W zwi─ůzku z tym, nim pod─ů┼╝y┼éem t─ů drog─ů, wr├│ci┼éem do wpisu J├╝rgen Gutsch, kt├│ry opisa┼é nieco inne podej┼Ťcie do procesu migracji.

J├╝rgen zamiast pythona wykorzysta┼é skrypt w C#, w zwi─ůzku z tym, uruchomienie go w innym ┼Ťrodowisku ni┼╝ Windows mo┼╝e by─ç bardziej skomplikowane. Na szcz─Ö┼Ťcie Microsoft udost─Öpni┼é .NET Framework oraz .NET Core r├│wnie┼╝ dla innych system├│w operacyjnych, wi─Öc by┼éa nadzieja!

Importowanie komentarzy ÔÇö podej┼Ťcie drugie #

Utterances pozwala powi─ůza─ç wpis na stronie z komentarzem (GitHub Issue) mi─Ödzy innymi przy pomocy tytu┼éu strony (title), pe┼énego adresu (url) lub adresu skr├│conego, bez przedrostka domeny (pathname).

Dla mnie pathname by┼é tym, czego szuka┼éem, w├│wczas tytu┼é GitHub Issue wygl─ůda┼éby nast─Öpuj─ůco ÔÇî/przywracanie-grub-boot-loadera-po-instalacji-windowsa/.

Przeanalizowa┼éem wpis J├╝rgena i zauwa┼╝y┼éem, ┼╝e skoncentrowa┼é on si─Ö na GitHub Issue bazuj─ůce na Tytule wpisu (title).

Przyznaj─ůc si─Ö szczerze, nie jestem programist─ů i od samego patrzenia na wpis J├╝rgena stwierdzi┼éem, ┼╝e jest to nieco za du┼╝o na moje do┼Ťwiadczenie (trzeba zna─ç swoje limity i wiedzie─ç, kiedy powiedzie─ç pass). W zwi─ůzku z tym zacz─ů┼éem moje dalsze poszukiwania.

Oczywi┼Ťcie, je┼╝eli czujesz si─Ö mocny w tej dziedzinie, warto spr├│bowa─ç. W przeciwie┼ästwie do pierwszego podej┼Ťcia skrypt J├╝rgena nie potrzebuje (jeszcze) dzia┼éaj─ůcego Utterances na stronie. W ramach procesu importu utworzy on niezb─Ödne GitHub Issues, kt├│re p├│┼║niej b─Ödzie mo┼╝na wykorzysta─ç z Utterances.

Importowanie komentarzy ÔÇö podej┼Ťcie trzecie #

I tak natrafiłem na repozytorium harttle/disqus2github na GitHub.

Ca┼éo┼Ť─ç wygl─ůda┼éa bardzo prosto i przejrzy┼Ťcie. Sprawdzaj─ůc, jak autor z importowa┼é wpisy do swojej strony wszystko wygl─ůda┼éo tak, jak bym chcia┼é.

Oczywi┼Ťcie, pami─Öta┼éem o dostosowaniu (spolszczeniu) fraz przed importem, oraz problem, na kt├│ry natrafili zar├│wno J├╝rgen jak i Pawamoy skutkuj─ůcy konieczno┼Ťci dodania op├│┼║nienie kilkusekundowego do procedury importu, aby nie zosta─ç zbanowanym przez system GitHub.

A więc pobrałem repozytorium harttle/disqus2github. Po czym otworzyłem w Atom w celu dostosowania.

Disqus2GitHub Atom

Rozpocz─ů┼éem od zmiany w config.example.json wprowadzaj─ůc moje repozytorium oraz token, kt├│ry wygenerowali┼Ťmy wcze┼Ťniej.

{
  "repo": "idarek/dariusz.wieckiewicz.org",
  "xmlFile": "./data.xml",
  "token": "naszWygenerowanyToken"
}

Następnie zmieniłem nazwę pliku z config.example.json na config.json.

Nasze wyeksportowane komentarze z Disqus (*-all.xml.gz) rozpakowałem i zmieniłem nazwę na data.xml.

W pliku github.js zmieniłem linijkę 8 z:

body: comment.message + '\n\nBy ' + comment.author + ' ' + comment.date

na:

body: comment.message + '\n\nPrzez ' + comment.author + ' ' + comment.date

Pora na instalację niezbędnych modułów oraz wykonanie importu.

npm install node index.js

Oczywi┼Ťcie, musimy mie─ç node zainstalowany w systemie

brew install node

Nie wiesz, czym jest Brew? Jest to menad┼╝er pakiet├│w, kt├│ry rozszerza znacz─ůco mo┼╝liwo┼Ťci system macOS (osobi┼Ťcie przypomina mi apt z systemu Debian/Ubuntu).

Niestety, nie wszystko posz┼éo po my┼Ťli, a konsola wyrzuci┼éa ton─Ö b┼é─Öd├│w, a import nie nast─ůpi┼é.

Problem okazał się node-expat oraz xml2json.

Napisa┼éem do Autora (Jun Yang) z zapytaniem, ale otrzymana odpowied┼║ zniech─Öci┼éa mnie do dalszej zabawy z tym rozwi─ůzaniem.

“(…) Try upgrade it or replace with another xml parser. This repo is meant to be a scaffold instead of a versatile cli tool. Try tweak it around and if you find it useful for everyone (…)”

No nic, dalsze poszukiwania trzeba zacz─ů─ç.

Importowanie komentarzy ÔÇö podej┼Ťcie czwarte #

I tak w moich dalszych poszukiwaniach natrafi┼éem na stron─Ö Fran├žois-Xavier Cat (przyznam szczerze, ┼╝e przeplot┼éa si─Ö ona wcze┼Ťniej przez moje okno przegl─ůdarki). Na swoim wpisie zatytu┼éowanym Moving my blog comments from Disqus to Github issues using PowerShell opisa┼é on metod─Ö na wykorzystanie PowerShell do importu komentarzy.

Jako że PowerShell nie jest mi obcy, gdyż jest wszechobecny w Windows 10 oraz można go zainstalować w macOS, postanowiłem spróbować.

W tym celu u┼╝y┼éem Homebrew (Brew), tak jak wspomnia┼éem wcze┼Ťniej.

brew install powershell

I tak z poziomu terminala mamy dost─Öpn─ů komend─Ö pwsh w celu uruchomienia PowerShell.

Fran├žois-Xavier Cat odwali┼é kawa┼é dobrej roboty, opisuj─ůc dlaczego zdecydowa┼é si─Ö na rezygnacje z Disqus, przedstawiaj─ůc plusy i minusy ca┼éego zamieszania.

W moim podej┼Ťciu postanowi┼éem wykorzysta─ç ten sam plan, kt├│ry wst─Öpnie autor za┼éo┼╝y┼é, pomijaj─ůc eksport komentarzy, kt├│ry dokona┼éem na samym pocz─ůtku.

Nim zacz─ů┼éem poni┼╝sze dzia┼éania, otworzy┼éem m├│j plik exportu XML w Atom i zmieni┼éem wszystkie odno┼Ťniki http:// na https:// gdy┼╝ moja strona serwowana jest wy┼é─ůcznie przez bezpieczne po┼é─ůczenie z zielon─ů k┼é├│dk─ů. By┼éo tego w sumie 272 pozycje, a Atom poradzi┼é sobie w sekund─Ö :).

Uruchomi┼éem pwsh i za┼éadowa┼éem komentarze nast─Öpuj─ůc─ů komend─ů.

# Load the file
$Disqus = Get-Content -Path ./dariuszwieckiewicz-all.xml

# Cast the file to XML format
$DisqusXML = ([xml]$Disqus).disqus

# Output result
$DisqusXML

Na etapie wyj┼Ťciowym (output) otrzyma┼éem:

xmlns          : http://disqus.com
dsq            : http://disqus.com/disqus-internals
xsi            : http://www.w3.org/2001/XMLSchema-instance
schemaLocation : http://disqus.com/api/schemas/1.0/disqus.xsd http://disqus.com/api/schemas/1.0/disqus-internals.xsd
category       : category
thread         : {thread, thread, thread, threadÔÇŽ}
post           : {post, post, post, postÔÇŽ}

Eksport z Disqus nie jest przyjazny u┼╝ytkownikowi. Wpisy i komentarze porozrzucane s─ů po ca┼éym pliku i powi─ůzane przez thread, posts oraz unikalny identyfikator (ID).

W pierwszej kolejno┼Ťci autor skupi┼é si─Ö na odpowiednim obrobieniu informacji, zaczynaj─ůc od samych komentarzy.

# Retrieve all Comments
$AllComments = $DisqusXML.post

# Retrieve properties available for each comments
$Properties = $AllComments | Get-Member -MemberType Property

# Process each Comments
$AllComments | Foreach-Object -process {

  # Store the current comment
  $Comment = $_

  # Create Hashtable to store properties of the current comment
  $Post = @{}

  # Go through each properties of each comments
  foreach ($prop in $Properties.name)
  {
     if($prop -eq 'id')
     {
        # Capture Unique IDs
        $Post.DsqID = $Comment.id[0]
        $Post.ID = $Comment.id[1]
     }
     elseif($prop -eq 'author')
     {
        # Author information
        $Post.AuthorName = $Comment.author.name
        $Post.AuthorIsAnonymous = $Comment.author.isanonymous
     }
     elseif($prop -eq 'thread')
     {
        # Here is the important data about the
        #  thread the comment belong to
        $Post.ThreadId = $Comment.thread.id
     }
     elseif($prop -eq 'message')
     {
        $Post.Message = $Comment.message.'#cdata-section'
     }
     else{
        # Other properties
        $Post.$prop = ($Comment |
            Select-Object -ExpandProperty $prop ) -replace '`r`n'
     }
     # Keep the original comment data structure if we need it later
     $Post.raw = $Comment
  }
  # Return a PowerShell object for the current comment
  New-Object -TypeName PSObject -Property $Post
}

Aby zobaczy─ç, jak wszystko wygl─ůda wykonujemy komend─Ö $DisqusXML.post

Nast─Öpnie, to samo dla w─ůtk├│w (wpis├│w).

# Retrieve threads
$AllThreads = $DisqusXML.thread

# Retrieve Thread properties
$Properties = $AllThreads |
    Get-Member -MemberType Property

# Process each threads
$AllThreads=$AllThreads | Foreach-Object -process {

    # Capture Current ThreadItem
    $ThreadItem = $_

    # Create Hashtable for our final object
    $ThreadObj = @{}

    # Go through each properties of each threads
    foreach ($prop in $Properties.name)
    {
        if($prop -eq 'id')
        {
            # Thread ID
            $ThreadObj.ID = $ThreadItem.id[0]
        }
        elseif($prop -eq 'author')
        {
            # Author
            $ThreadObj.AuthorName = $ThreadItem.author.name
            $ThreadObj.AuthorIsAnonymous = $ThreadItem.author.isanonymous
            $ThreadObj.AuthorUsername = $ThreadItem.author.username
        }
        elseif($prop -eq 'message')
        {
            $ThreadObj.Message = $ThreadItem.message.'#cdata-section'
        }
        elseif($prop -eq 'category')
        {
            $ThreadObj.Category = ($ThreadItem|
                Select-Object -ExpandProperty $prop).id
        }
        else{
            # Other properties
            $ThreadObj.$prop = ($ThreadItem |
                Select-Object -ExpandProperty $prop) -replace '`r`n'
        }
        $ThreadObj.raw = $ThreadItem
    }
    # Return a PowerShell object for the current ThreadItem
    New-Object -TypeName PSObject -Property $ThreadObj
}

Aby zobaczy─ç, jak wszystko wygl─ůda wykonujemy komend─Ö $DisqusXML.thread

Po tym kroku autor wspomnia┼é o ┼Ťmieciach, kt├│re nagromadzi┼éy si─Ö w jego systemie komentarzy na prze┼éomie lat oraz podczas u┼╝ywania przez niego r├│┼╝nych platform do publikacji jego tw├│rczo┼Ťci.

Osobi┼Ťcie pomin─ů┼éem ten krok, gdy┼╝ nie mia┼éem z tym problemu. Odk─ůd zacz─ů┼éem korzysta─ç z Disqus, moja strona zagnie┼║dzi┼éa si─Ö na dobre z obecnym adresem strony.

Nim autor zdecydowa┼é si─Ö na po┼é─ůczenie wpis├│w z komentarzami, postanowi┼é wprowadzi─ç procedur─Ö sprawdzaj─ůc─ů tytu┼é wpisu z aktualnie dzia┼éaj─ůc─ů stron─ů. Mia┼éo to na celu uzupe┼énienie ewentualnych brak├│w w eksporcie z Disqus (r├│wnie┼╝ to pomin─ů┼éem w moim imporcie).

Dodatkowo postanowi┼é usun─ů─ç nieco ┼Ťmieci z tytu┼é├│w wpis├│w oraz pozostawi─ç w odno┼Ťniku do pliku tylko pathname.

# Create 2 properties 'link2' and 'title2' that will contains the clean information
#  then group per link (per thread or post)
#  link2: trimed URL
#  title2: Remove prefix, weird brackets or weird characters, Encoding issues
$AllThreads = $threads|
  Select-Object -Property *,
  @{L='link2';E={
      $_.link -replace "
        https://|http://|www\.|
        lazywinadmin\.com|
        lazywinadmin\.github\.io|
        \/minimal-mistakes|
        \/powershell"}},
  @{L='title2';E={
      $_.title -replace "^LazyWinAdmin:\s" `
        -replace '├óÔéČÔäó',"'" `
        -replace "├â┬ó├óÔÇÜ┬Č├é┬Ž|├óÔéČ┬Ž" `
        -replace '├óÔéČÔÇť','-' `
        -replace '\/\[','[' `
        -replace '\\\/\]',']' }}|
  Group-Object -Property link2

W moim przypadku wygl─ůda┼éoby to nast─Öpuj─ůco.

$AllThreads = $threads|
  Select-Object -Property *,
  @{L='link2';E={
      $_.link -replace "
        https://|http://|www\.|
        dariusz\.wieckiewicz\.org"}},
  @{L='title2';E={
      $_.title
        -replace " // Dariusz Wi─Öckiewicz","" `
        -replace "&#8230;","..." `
        -replace "&#8222;",'"' `
        -replace "&#8221;",'"' `
        -replace "&#8211;",'-' }}|
  Group-Object -Property link2

Pora na po┼é─ůczenie komentarzy ze wpisami.

# Append the thread information to the each comment object
# Here we just pass the realtitle and link2
$AllTogether = $Comments | ForEach-Object -Process {
    $CommentItem = $_
    $ThreadInformation = $ThreadsUpdated |
        Where-Object -FilterScript {
            $_.id -match $CommentItem.ThreadId
        }

    $CommentItem |
        Select-Object -Property *,
            @{L='ThreadTitle';E={$ThreadInformation.title2}},
            @{L='ThreadLink';E={$ThreadInformation.link2}}
} |
Group-Object -Property ThreadLink |
Where-Object -FilterScript {$_.name}

Je┼╝eli wszystko przesz┼éo poprawnie, gotowi jeste┼Ťmy na utworzenie GitHub Issue oraz dodanie naszych komentarzy.

W tym celu niezb─Ödne b─Ödzie doinstalowanie modu┼éu PowerShellForGithub do PowerShell oraz dodanie naszych danych uwierzytelniaj─ůcych.

# First fetch the module from the PowerShell Gallery
Install-Module -Name powershellforgithub -scope currentuser -verbose
# Import it
Import-Module -Name powershellforgithub

# Specify our Github Token
$key = 'naszWygenerowanyToken'
$KeySec = ConvertTo-SecureString $key -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ('username_is_ignored', $KeySec)

# Set Connection and configuration
Set-GitHubAuthentication -Credential $cred
Set-GitHubConfiguration -DisableLogging -DisableTelemetry

Zmieniamy tylko naszWygenerowanyToken na Token API, kt├│ry wygenerowali┼Ťmy na pocz─ůtku tego wpisu.

Teraz jeste┼Ťmy gotowi na import, dokonuj─ůc nieco dostosowania do naszego ┼Ťrodowiska (OwnerName, RepositoryName, BlogUrl) oraz spolszczaj─ůc co nieco.

# Define Github commands default params
$GithubSplat = @{
    OwnerName = 'idarek'
    RepositoryName = 'dariusz.wieckiewicz.org'
}
$BlogUrl = 'https://dariusz.wieckiewicz.org'

# Retrieve issues
$issues = Get-GitHubIssue @githubsplat

# Process each threads with their comments
$AllTogether |
Sort-Object name -Descending |
ForEach-Object -Process{

    # Capture current thread
    $BlogPost = $_

    # Issue Title, replace the first / and
    #  remove the html at the end of the name
    $IssueTitle = $BlogPost.name -replace '^\/' -replace '\.html'

    # lookup for existing issue
    $IssueObject = $issues|
        Where-Object -filterscript {$_.title -eq $IssueTitle}

    if(-not $IssueObject)
    {
        # Build Header of the post
        $IssueHeader = $BlogPost.group.ThreadTitle |
          select-object -first 1

        # Define blog post link
        $BlogPostLink = "$($BlogUrl)$($BlogPost.name)"

        # Define body of the issue
        $Body = @"
# $IssueHeader

[$BlogPostLink]($BlogPostLink)

<!--
Imported via PowerShell on $(Get-Date -Format o)
-->
"@
        # Create an issue
        $IssueObject = New-GitHubIssue @githubsplat `
            -Title $IssueTitle `
            -Body $body `
            -Label 'blog comments'
    }

    # Sort comment by createdAt
    $BlogPost.group|
      Where-Object {$_.isspam -like '*false*'} |
      Sort-Object createdAt |
      ForEach-Object{

        # Current comment
        $CurrenComment = $_

        # Define body of the comment
        $CommentBody = @"
**Dodano**: ``$($CurrenComment.createdAt)``
$($CurrenComment.message)

<!--
Imported via PowerShell on $(Get-Date -Format o)
Json_original_message:
$($CurrenComment|Select-Object -ExcludeProperty raw|convertTo-Json)
-->
"@
        # Create Comment
        New-GitHubComment @githubsplat `
            -Issue $IssueObject.number `
            -Body $CommentBody
    }
    # Close issue
    Update-GitHubIssue @githubsplat `
        -Issue $IssueObject.number `
        -State Closed
}

I co, i nic! W moim przypadku nie zadzia┼éa┼éo. Po raz kolejny, moje do┼Ťwiadczenie jest niewystarczaj─ůce, ┼╝eby znale┼║─ç przyczyn─Ö.

Kolejne rozwi─ůzanie (mimo ┼╝e prawdopodobnie poprawne) do ┼Ťmieci a ja wr├│ci┼éem do punktu wyj┼Ťcia.

Importowanie komentarzy ÔÇö podej┼Ťcie pi─ůte #

Jako ┼╝e liczba dzia┼éaj─ůcych sposob├│w poniek─ůd si─Ö wyczerpa┼éa, pozosta┼éa ostatnia metoda ÔÇö manualna, tak jak opisa┼é to Nan Xiao w punkcie 2 procesu migracji.

To skoro ju┼╝ zamierzam zrobi─ç to r─Öcznie, to dlaczego by nie wr├│ci─ç do podej┼Ťcia pierwszego od pawamoy i jego p├│┼éautomatycznego importu.

Przypominaj─ůc.

Aby podej┼Ťcie pierwsze zadzia┼éa┼éo, Utterances musi ju┼╝ dzia┼éa─ç, w zwi─ůzku z tym skoczymy najpierw nieco do przodu.

Nie kontynuuj czytania poni┼╝ej ÔÇö przejd┼║ (kliknij) do przodu. Na dalszy etapie wr├│cisz do poni┼╝szego paragrafu. W przeciwnym razie b─Ödzie ci si─Ö wszystko wydawa┼éo oderwane od rzeczywisto┼Ťci.


Dalej #

Skoro mamy ju┼╝ aktywny i dzia┼éaj─ůcy system komentarzy, pora na import z Disqus.

┼╗eby dowiedzie─ç si─Ö, kt├│re wpisy posiadaj─ů komentarze, wykorzysta┼éem do tego Terminal macOS.

more dariuszwieckiewicz-all.xml | grep "thread dsq:id" | grep ">"

Dzi─Öki temu otrzyma┼éem bogat─ů list─Ö:

(...)
<thread dsq:id="6892197256">
<thread dsq:id="6892197256">
<thread dsq:id="6892178219">
<thread dsq:id="6892178219">
<thread dsq:id="7905495271">
<thread dsq:id="7905495271">
<thread dsq:id="7905495271">
<thread dsq:id="6892197256">
<thread dsq:id="6892197256">
(...)

Tylko 181 odno┼Ťnik├│w ­čś▒

Na szcz─Ö┼Ťcie sporo z nich si─Ö powtarza, ┼Ťwiadcz─ůc o kilku komentarzach w tym samym wpisie.

Posortowa┼éem i usun─ů┼éem duplikaty i tak zosta┼éo mi 41 wpis├│w z komentarzami.

Teraz, przeszukuj─ůc m├│j plik XML, musia┼éem znale┼║─ç URL odpowiadaj─ůcy otrzymanemu numerowi.

Irytuj─ůce sta┼éo si─Ö to, ┼╝e Disqus powi─ůza┼é komentarze z adresami URL, kt├│re mia┼éem lata temu, jeszcze przed pozbyciem si─Ö daty z URL, podczas gdy teraz wszystkie moje wpisy posiadaj─ů pojedynczy pathname.

Na szcz─Ö┼Ťcie dotyczy┼éo ty tylko 11 wpis├│w sprzed 2014 roku, kt├│re mog┼éem zmieni─ç r─Öcznie.

Dzi─Öki temu otrzyma┼éem 33 wpisy z komentarzami, na kt├│rych musia┼éem napisa─ç test aby zainicjowa─ç GitHub Issue i umo┼╝liwi─ç mi p├│┼║niejszy import metod─ů pawamoy.

W przypadku Hugo mo┼╝na to by┼éo zrobi─ç, uruchamiaj─ůc go lokalnie lub zdecydowa─ç si─Ö na prac─Ö Online. Osobi┼Ťcie sprawdzi┼éem wszystko online, aby upewni─ç si─Ö, ┼╝e nie robi─Ö nic na darmo, a wszystko dzia┼éa tak jak trzeba.

Nim jednak zacz─ů┼éem, doinstalowa┼éem python3 za pomoc─ů brew install python3 w moim systemie oraz zaktualizowa┼éem pip3.

sudo -H pip3 install --upgrade pip --force-reinstall

Nast─Öpnie zainstalowa┼éem niezb─Ödne pakiety dodatkowe PyGithub oraz xmltodict (bez konieczno┼Ťci ich pobierania).

pip3 install PyGithub
pip3 install xmltodict

W terminalu wykonujemy poni┼╝sze komendy w celu ustawienia ┼Ťrodowiska startowego:

export FILEPATH="dariuszwieckiewicz-all.xml"
export USERNAME="idarek"
export TOKEN="naszWygenerowanyToken"
export REPOSITORY="idarek/dariusz.wieckiewicz.org"
export BASE_URL="https://dariusz.wieckiewicz.org/"

Nast─Öpnie przygotowujemy plik disqus.py wraz z poni┼╝szym skryptem odpowiadaj─ůcy za import.

Od siebie dodałem import os gdyż w macOS nie chciało bez tego działać.

import time
import os
import xmltodict
from github import Github

FILEPATH = os.environ["FILEPATH"]
USERNAME = os.environ["USERNAME"]
TOKEN = os.environ["TOKEN"]
REPOSITORY = os.environ["REPOSITORY"]
BASE_URL = os.environ["BASE_URL"]


def disqus_to_github():
    g = Github(TOKEN)
    repo = g.get_repo(REPOSITORY)
    issues = repo.get_issues()

    with open(FILEPATH) as fd:
        data = xmltodict.parse(fd.read())

    data = data["disqus"]

    threads = [dict(t) for t in data["thread"]]
    posts = sorted((dict(p) for p in data["post"]), key=lambda d: d["createdAt"])

    # only keep threads with comments
    twc_ids = set(p["thread"]["@dsq:id"] for p in posts)
    threads = {t["@dsq:id"]: t for t in threads if t["@dsq:id"] in twc_ids}

    # associate the thread to each post
    for post in posts:
        post["thread"] = threads[post["thread"]["@dsq:id"]]

    # associate the related GitHub issue to each thread
    # warning: the issues need to exist before you run this script!
    # write a "test" comment in each one of your post with comments
    # to make Utterances create the initial issues
    for thread in threads.values():
        for issue in issues:
            if issue.title == thread["link"].replace(BASE_URL, ""):
                thread["issue"] = issue
                break

    # iterate on posts and create issues comments accordingly
    for i, post in enumerate(posts, 1):
        name = post["author"]["name"]
        user = post["author"].get("username")
        mention = " @" + user if user and not user.startswith("disqus_") else ""
        date = post["createdAt"]
        message = post["message"]
        issue = post["thread"]["issue"]
        body = f"*Oryginalna data: {date}*\n\n{message}"
        # don't add original author when it's you
        if user != USERNAME:
            body = f"*Oryginalny autor:* **{name}{mention}**  \n{body}"
        print(f"Posting {i}/{len(posts)} to issue {issue.number}    \r", end="")
        issue.create_comment(body)
        # prevent hitting rate limits!
        time.sleep(0.5)

    print()


if __name__ == "__main__":
    disqus_to_github()

Zak┼éadaj─ůc, ┼╝e na wszystkie 33 wpisach doda┼éem testowy komentarz pora na uruchomienie naszego skryptu.

W macOS, z zainstalowany python3 za pomoc─ů brew wykona┼éem to nast─Öpuj─ůco:

FILEPATH="dariuszwieckiewicz-all.xml" USERNAME="idarek" TOKEN="naszWygenerowanyToken" REPOSITORY="idarek/dariusz.wieckiewicz.org" BASE_URL="https://dariusz.wieckiewicz.org" python3 disqus.py

Przy pierwszym uruchomieniu natrafiłem jednak na problem, który mnie nieco zirytował.

Traceback (most recent call last):
  File "disqus.py", line 74, in <module>
    disqus_to_github()
  File "disqus.py", line 52, in disqus_to_github
    issue = post["thread"]["issue"]
KeyError: 'issue'

Okaza┼éo si─Ö, ┼╝e moje obecne ┼Ťrodowisko domy┼Ťlnie usuwa / z ko┼äca adresu URL natomiast eksport z Disqus posiada┼é / w ka┼╝dym linku. Raz jeszcze musia┼éem u┼╝y─ç Atom, aby hurtowo to zmieni─ç (/</link> na </link>).

I tak po ponownym uruchomieniu wszystko zaczęło działać. Po dłuższej chwili ujrzałem:

Posting 181/181 to issue 11

Pora na sprawdzenie.

Disqus2GitHub Imported

Yuppi! Wszystko zostało z importowane.

I mimo tego, ┼╝e wygl─ůda to poniek─ůd dziwnie (wszystkie komentarze z importowane napisane przez mnie), to inaczej si─Ö nie da┼éo.

Teraz wystarczy usun─ů─ç wpisy “test” z ka┼╝dego z GitHub Issue i przejrze─ç, czy nie importowa┼é si─Ö jaki┼Ť spam :)

Przejdź do zakończenia.


Utterances #

Utterance jest lekkim systemem komentarzy bazuj─ůcy na GitHub Issues, a dok┼éadniej A lightweight comments widget built on GitHub issues.

Repozytorium #

Nim zaczniemy wstawia─ç Utternaces na nasz─ů stron─Ö, musimy utworzy─ç repozytorium kt├│re wykorzystamy do przechowywania komentarzy.

Po zalogowaniu si─Ö na GitHub klikamy przycisk New przy repozytoriach.

Repositories NEW

Nast─Öpnie wybieramy nazw─Ö i przyznajemy publiczny dost─Öp (public_repo).

GitHub Create a new repository

Na moje repozytorium wybrałem idarek/dariusz.wieckiewicz.org.

Dost─Öp aplikacji Utterances #

Przechodzimy na stron─Ö aplikacji (GitHub App) Utterances, aby skonfigurowa─ç dost─Öp do naszego repozytorium.

GitHub App Utterances Config

Potwierdzamy przyznanie prawa do odczytu metadanych oraz odczytu i zapisu GitHub Issues.

Następnie wybieramy i dodajemy, do którego repozytorium aplikacja będzie miała dostęp.

Utterances Configuration

Generowanie kodu na stron─Ö #

Wracaj─ůc na stron─Ö g┼é├│wn─ů utteranc.es przechodzimy do sekcji pola repo: gdzie wpisujemy nasze repozytorium, a nast─Öpnie do Blog Posts <> Issue Mapping.

Tutaj wybieramy, w jaki spos├│b GitHub Issues b─Öd─ů tworzone.

Je┼╝eli czytasz od pocz─ůtku, osobi┼Ťcie zale┼╝a┼éo mi, aby tytu┼é GitHub Issue by┼é odpowiednikiem pathname. Jest to pierwsza, domy┼Ťlna opcja przy konfiguracji ze strony Utterances.

Utterances Blog Post Issue Mapping

Nast─Öpnie wybieramy, jak─ů etykiet─Ö ka┼╝dy z naszych GitHub Issues b─Ödzie mia┼é przypisan─ů.

Dzi─Öki temu mo┼╝emy pogrupowa─ç GitHub Issues utworzone przez nasz─ů stron─Ö oraz bezpo┼Ťrednio z GitHub. Jest to szczeg├│lnie przydatne, je┼╝eli dane repozytorium u┼╝ywamy do wi─Öcej ni┼╝ do cel├│w komentarzy.

Utterances Issue Label

Nast─Öpnie wybieramy motyw. W moim przypadku, jako ┼╝e mam wprowadzony tryb jasny i ciemny strony, kt├│ry zmienia si─Ö automatycznie (oraz za pomoc─ů ikony na g├│rze strony) wybra┼éem Preferred Color Scheme.

Utterances Theme

I tak doszli┼Ťmy do kodu, kt├│ry umo┼╝liwi nam dodanie systemu komentarzy bazuj─ůcego na Utterances na naszej stronie.

Utterances Enable

W moim przypadku kod ko┼äcowy wygl─ůda┼é nast─Öpuj─ůco:

<script defer src="https://utteranc.es/client.js"
        repo="idarek/dariusz.wieckiewicz.org"
        issue-term="pathname"
        label="comment"
        theme="preferred-color-scheme"
        crossorigin="anonymous"
        async>
</script>

Od siebie dodałem słowo defer w celu opóźnienia ładowania skryptu do momentu, gdy jest on potrzebny.

Opr├│cz samego jego dodania pozostaje nam odpowiednie dostosowanie za pomoc─ů CSS oraz .utterances i .utterances-frame.

Je┼╝eli kontynuujesz czytanie z pi─ůtego podej┼Ťcia, klikamy tutaj i wracamy do czytania.


Na koniec #

Cel osi─ůgni─Öty!

Mimo tego, ┼╝e pr├│bowa┼éem przer├│┼╝nych metod, w zwi─ůzku z moimi ograniczeniami programistycznym (nie jestem programist─ů) uda┼éo mi si─Ö doj┼Ť─ç do ko┼äca.

Przyznam szczerze, ┼╝e w pewnym momencie chcia┼éem da─ç za wygran─ů i darowa─ç sobie import, a nawet usuni─Öcie ca┼éego powy┼╝szego wpisu, na kt├│ry po┼Ťwi─Öci┼éem sporo czasu.

Czasami przerwa pomaga w przemy┼Ťleniu, dzi─Öki czemu mog─Ö napisa─ç teraz… sukces!

Nowy system komentarzy mo┼╝ecie podziwia─ç poni┼╝ej.

Pozdrawiam.

Komentarze
Kategorie