WoltLab Cloud Discord-Sync 1.1.4

With this plugin you can synchronize you user groups between woltlab suite core and discord.

Many communities know it: there is a homepage and a discord server. However, especially with a high number of members, you don't want to assign the roles in Discord manually to every user. The Woltlab Suite Plugin Discord Synchronisation provides a remedy.

Features

  • automatic connection to discord server after connection between WSC account and discord account
  • Synchronization of user groups to users in Discord
  • Takeover of the avatar from Discord
  • Synchronization from bans to discord
  • Synchronization of the user name (when first connecting to Discord)
  • Discord-Login

Requirements

WoltLab Suite 5.3 or higher

PHP 7.2or higher

Instructions

The manual for this plugin can be found on my homepage: https://hanashi.eu/article/6-a…d-sync-plugin-nun-fertig/

Support is only available in the support forum or the discord.

Questions

Question: My bot is always displayed offline. Is this correct?

Answer: Yes that is correct. The bot is always displayed offline, because the implementation of the Discord Gateway is too complex. If you still want to see your bot permanently online, I have created a little tutorial in faq.


Question: Unknown Error always occurs when connecting. What can I do?

Answer: If Unknown Error comes, you have entered the wrong Redirect URI. Enter the Redirect URI that is displayed in the ACP..

What happens after the purchase?

Create a user account on hanashi.dev. In your settings, go to Activate purchases. And enter your API information from the API Access page. Now click Submit. You have now activated access to the support forum.

Images

  • Version 1.1.4

    • CHANGE: Update for discord api
  • Version 1.1.3

    • FEATURE: hint option if not connected to Discord
    • FIX: authentication error
  • Version 1.1.2

    • FIX: problem with discord avatar unter WoltLab Suite 5.3
    • FIX: problem with conditions
  • Version 1.1.1

    • CHANGE: DiscordAvatar no longer inherits from DefaultAvatar, but implements the necessary interfaces directly.
  • Version 1.1.0

    Attention: At least WoltLab Suite 5.3 is now required.

    • CHANGE: switch to Database PHP API
    • CHANGE: updated included Discord API
    • CHANGE: unused uses removed
    • CHANGE: deprecated code replaced
    • CHANGE: Avatar functionality rewritten
    • CHANGE: removed rudimentary debug mode and replaced it with WoltLab Suite debug mode
    • FEATURE: selection of Discord bots in ACP simplified
    • FEATURE: it is now possible to set user group-dependent that Discord users must have MFA enabled in Discord to use Discord Sync
    • FIX: groups in Discord were not removed when user had no groups in WoltLab Suite
  • Version 1.0.8

    • CHANGE: change to PSR-12
  • Version 1.0.7

    • FIX: Sync error with group duplicates
    • FIX: Nickname was only synchronised in the 2nd run during the Sync-Cronjob
    • CHANGE: Pre-adjustment for WSC 5.4
  • Version 1.0.6

    • CHANGE: Added exceptions for two step verification and TeamSpeak sync for mandatory sync.
    • FIX: Banns over warnings are now synchronised
    • FIX: several minor bugs
    • FIX: Groups of the server owner are synchronised (the nickname of the server owner can still not be synchronised)
  • Version 1.0.5

    • FEATURE: Registration via Discord can be disabled
  • Version 1.0.4

    • CHANGE: Manage groups can be used again
  • Moin,


    Der Bot funktioniert bei mir soweit, ist auf dem Server, hat Rechte, Bot Gruppe ist ganz oben.. jedoch wird mir bei der Rangbearbeitung im ACP keine Rollen angezeigt.


    Hoffe auf Hilfe :)

    Gruß Marschl

  • Hallo Hanashi
    Ich habe das problem wenn ich jemand bann und Banns synchronisieren an habe

    passiert das dennoch nicht in discord und der bot hat administrator rechte also alles

    woran liegt das das es bei mir nicht synchronisiert


    mfg

    • Hallo,


      es gibt dazu bereits ein Thema in meinem Supportforum dazu. Ich versuche das aktuelle durch längere Tests zu reproduzieren, um einen Fix bringen zu können.

  • Hi, do the bot deletes automatically the role from discord if it gets removed from the forum as well? thanks.

    • Hi, the bot does not delete groups, he just removes or adds user group assignments.

    • oh yeah sorry, that's what I meant, if the bot removes a user from a group if he gets it removed from the forum hahaha.

  • Hallo Hanashi, hat man als Admin die Möglichkeit, diese beiden Features zu de-/aktivieren?

    Quote

    Übernahme des Avatars von Discord

    Synchronisierung des Benutzernamens (beim erstmaligen Verbinden mit Discord)

    MfG Trouble

    • Hallo,


      beide Features können über globale Optionen de-/aktiviert werden.

      Thanks 1
    • Hab noch was vergessen: Wird der User gefragt, ob Avatar und Benutzername übernommen werden? Falls nicht, gibt es eine Benachrichtigung?

    • Der Avatar wird derzeitig nur vom Discord zum Forum übernommen. Dafür muss der Benutzer aktiv vorgehen.

      Der Benutzername in Richtung des Discordw wird allerdings automatisch übernommen sobald der Benutzer die Konten verknüpft. Außer die Option ist aus.

    • Super, vielen lieben Dank für die ausführliche Antwort :)

  • Hey, erstmal echt geiles Plugin. Habe beides TS und DC. Eine Frage habe ich aber. Kann man das ändern von Namen ausstellen? Der übernimmt ja überall den Namen aus dem Forum^^

  • Hallo, ist es möglich den Discord Namen nach der Verknüpfung im Benutzerprofilfeld anzeigen zu lassen?

    • Hallo,


      derzeitig noch nicht. Es ist aber bereits für eine spätere Version geplant.

      Like 2
  • Wenn sich ein User im Forum mit Discord verbinden möchte kommt immer unknown applikation

    • Hallo,


      dann wurde das Plugin nicht korrekt konfiguriert. Die Anleitung findest du auf meiner Seite im FAQ.

  • Hab das Forum neu aufgesetzt, alte Daten importiert und Discord Sync installiert:

    Benutzer werden zwar wie vorher dem Discord-Server hinzugefügt oder entfernt aber die Rollen werden nicht mehr zugewiesen.

    - habe den Bot schon mehrmals neu angelegt und mit dem Discord verbunden (Administrator)

    - Die Rollen werden im ACP in den Benutzergruppen angezeigt und sind auch dort ausgewählt


    Es gibt leider auch keine Fehlermeldung, Cronjobs manuell ausführen hilft auch nicht.. bin ratlos

    • Hallo,


      wurde die Bot-Gruppe in Discord nach ganz oben geschoben?

    • Ah, OK das wr es wohl was ich übersehen hatte... Danke!

  • Guten,


    ist der Bug mit der Sicherheitslücke schon bekannt ?

    Wenn ja, wann kommt dazu ein Fix ?


    Grüße

    • Hallo,


      bisher ist mir keine Sicherheitslücke bekannt.


      Falls du eine potentielle Sicherheitslücke gefunden hast, kannst du diese gerne per Ticket bei mir im Forum oder per E-Mail an info@hanashi.dev melden.

    • Email ist raus.

    • Hallo,


      ich habe geprüft was du geschrieben hast. Das von dir geschilderte Verhalten ist keine Sicherheitslücke an sich. Prinzipiell solltest du nur Personen auf das ACP Zugriff geben, denen du wirklich vertraust. Das Auslesen des Tokens ist nur als Admin oder mit Datenbankzugriff möglich.

    • Hallo,


      in der Version 2.0.0 der Discord-API wird der Bot-Token und der Client-Secret übers ACP beim Bearbeiten eines Bots nicht mehr angezeigt. Beide Informationen werden trotzdem unverschlüsselt in der Datenbank gespeichert.


      Mit der WoltLab Suite 5.4 empfehle ich für das ganze Team Multi-Faktor-Authentifizierung verpflichtend zu aktivieren.

    • Guten Abend, dankeschön für die Information. Entschuldige, ich hatte eine Zeit lang nicht reingeschaut gehab.

  • Bei mir Sync der Bot warum auch immer keine Gruppe...
    Habe alle Bot Einstellungen überprüft sowie rechte...


    MfG. Max

  • I have installed this app and created and connected the bot.


    I only want to have 1 user group sync with discord, where do i create the settings for this?

    • I see it now, it showed up in the User Groups setting.


      Also, if you select a Discord Sync in the user group, is there a way to unselect it?

    • Yes, this possible. Hold CTRL on Windows or CMD on macOS and click on the selected group.


      I will rebuild this in the future with checkboxes.

  • Ich habe seit einigen Tagen das Problem das der Bot meines Forums nicht mehr auf meinem Discord Server erscheint und seitdem auch keine Synchronisation mehr stattfinden kann. Habe allerdings an den Einstellungen nichts geändert seit der Installation und Einrichtung des Plugins. Funktionierte bis vor wenigen Tagen auch ohne Probleme.

    Gab es irgendein Update das diesen Bug verursacht?

    • Hallo,


      der Bot wird standardmäßig nicht in Discord als online angezeigt. Klingt aber bei dir so als hätte jemand den Bot vom Server geworfen. Melde dich doch auch gerne im offiziellen Supportforum, falls du weitere Fragen dazu hast.

  • In welchen interval wird der Rang synchronisiert? Wenn ich Ränge im Forum setze, werden diese nicht im Discord übernommen.
    Der Discord bot wird auch nicht als online angezeigt. Wenn ich den bot über die Botliste online schalte, wird er kurz angezeigt.

    • Hallo, Benutzergruppen werden Instant synchronisiert, wenn diese einem Benutzer zugewiesen werden. Hast du denn auch Server Members Intent im Bot akitiviert?

      Der Bot selbst wird nie als online angezeigt, siehe dazu auch in meinem FAQ auf meine Homepage.

    • Ja das habe ich vergessen, danke! Klappt alles. Super Plugin danke dafür! :)

    • Ich habe dich bei mir im Forum aktiviert :)

    • Ja leider weiß ich mein Passwort nicht mehr, und bekomme keine Emails von deinem Forum bei Web.de

    • Schau mal bitte ob du jetzt wieder Mails bekommst.

  • Benötigt das Paket „dev.hanashi.wsc.discord-api“ in Version „1.0.3“ oder höher, dies ist aber weder installiert noch wird es mitgeliefert.


    Ich kann das Plugin nicht installieren.

  • Ich kann die Anleitung auf deiner Seite nicht lesen, keine Berechtigung.

    • Hallo, die Anleitung steht verifizierten Kunden zur Verfügung.

    • Wir haben gerade das system gekauft aber haben keine rechte für die anleitung ...

    • @Extended-Reality in der Plugin-Beschreibung steht wie man Zugriff bekommt ;)

  • I cannot read instructions

    Access denied. You're not authorized to view this page.

    My name on your website is: Ford

  • The update from 0.6.5 to 0.6.7 does not seem to work.


    Code
    Cannot alter column 'discordOauth2Expires'. A package can only change own columns.
  • If we bought your other one how do we get your new updates since that one is no longer "available"

  • Please check your inbox mate!

  • ok... discord-sync und die dazugehörige Shotbox sind installiert. Wo gibt es ne Anleitung? Wie kann ich nun den Discord Chat verbinden?

    • ich hab es soweit hinbekommen. Mit dem Bot und so. Nur wenn ich ich einen Channel wähle, dann kommt ein Fehler:


      "Es ist ein Fehler mit der Discord-API aufgetreten. Missing Permissions"


      Welche Berechtigungen brauch das ganze nun genau?

  • Moin,
    jetzt habe ich mir extra dieses Plugin für die Shoutbox gekauft und nun ist diese nicht mehr erhältlich... und nun? Kommt da eine neue Shoutbox? Oder gibt es da eine andere Lösung? Sonst wüsste ich nicht wozu ich dieses Plugin brauche :o

    • Hallo, ich habe die Shoutbox vor einigen Tagen eingestellt, da diese nicht mehr von mir weiterentwickelt wird. In den nächsten Tagen/Wochen wird allerdings eine alternative Shoutbox mit Discord-Anbindung von einem anderen Anbieter erscheinen, welche ebenfalls mit Discord-Sync kompatibel sein wird.

    • cool... kannst du mir den anderen Hersteller nennen, damit ich das ganze verfolgen kann?

    • Das ist SoftCreatR. Es wird eine Erweiterung für seine bestehende Shoutbox.

    • ach die... oky. Thx :)

    • Ist meiner Meinung nach aktuell die beste auf dem Markt :)

  • Super Plugin, funktioniert einwandfrei!

    Nur eine Frage: Kann man eine Einstellung vornehmen, bei der man standardmässig den Discord-Avatar nach Registrierung verwendet?


    LG

    Arki

    • Hallo, bisher gibt es diese Einstellung nicht, kann ich aber für die Version 1.0.0 mit einplanen.


      VG

      Hanashi

      Like 1
  • Hi tolles plugin und funktioniert auch soweit. Nur kommt man als admin nicht mehr ins backend rein. Hat jemand eine lösung?

    • Hallo, Support zu diesem Plugin gibt es nur für Kunden und auch nur im Supportforum.

  • Hi Peter, kann man die log abschalten unsere ist an die 3 GB groß ?

    • Hi, einfach den Debug-Modus vom Discord-Sync ausmachen.

    • hopla wer hat den den angemacht. Danke ;)

  • Das Plugin scheint einen Fehler aufzuweisen.

    Leute können sich in meinem Forum nicht registrieren bzw einloggen.

    Es wird vom Forum behauptet das "Der GitHub Account bereits mit einem Account verlinkt" ist.

    (Your GitHub account is already connected to a different user)

    Ich sehe nicht in welcher Relevanz die GitHub Synchronisation zum Discord Sync steht, jedoch kann sich niemand einloggen momentan via Discord.

    • Hi, danke da habe ich tatsächlich vergessen eine Sprachvariable zu ersetzen. Wird gefixt.

  • Hallo, ich benötige etwas Hilfe. Hab die Anleitung soweit befolgt und es ist alles grün, jedoch Syncronisiert sich da überhaupt nichts. Der Bot wird im Discord unter Servereinstellungen -> Rollen Angezeigt, die Benutzergruppen von der Website jedoch nicht. Ebenso frage ich mich, wie er die Benutzer den entsprechenden Gruppen zuordnen will?


    LG Daniel

    • Okay, nachdem ich auf deiner Website nun die aktuelle Version gefunden habe, hab ich dann erst mal ein Update gemacht. Nach erneutem lesen und durchgehen der Anleitung, hab ich nun auch das mit der Redirekt URI verstanden, soweit ist also alles eingerichtet. Die Benutzergruppen aus dem WCF werden mir im Discord trotzdem nicht angezeigt, auch nach hinzufügen einer neuen Gruppe. Wenn ich die Gruppe manuell anlege und unter Benutzergruppen - beliebige Gruppe - eine Gruppe auswähle, tut sich da auch nichts..


      Wie funktioniert denn die Zuordnung der einzelnen User in die Gruppen? Ich mein, okay, selbst wenn die Benutzergruppen gesynct werden, woher weis der Discord, dass User XY aus dem Forum User XY im Discord ist, ohne eindeutige Client ID ?


      Bei dem Teamspeak Sync muss man auf der Website seine TS Ident. angeben, dass kann ich nachvollziehen und funktioniert. :D


      LG Daniel

    • Hab mich da auch Stunden beschäftigt damit ^^ am besten Du schaust direkt auf Hanashi`s Discordserver vorbei, dort wird Dir schnell geholfen... Top Support! (Ps die Anleitung darfste nicht ganz für voll nehmen, älteres Modell :) )

    • Die Anleitung ist mittlerweile aktualisiert :)

  • Hallo Hanashi


    Erstmal Danke für dieses Plugin. Eine Frage hätte ich.

    Wird die Synchro nur beim Verbinden ausgelöst oder nach einer gewissen Zeit wiederholt?

    • Die Synchro wird beim Verbinden ausgelöst und immer wenn eine Gruppe hinzugefügt oder entfernt wird.

      Like 1
    • Danke für die Antwort.

      Leider werden die Discord Rollen nur bei der Verknüpfung aktualisiert. Wenn Benutzergruppen hinzugefügt oder entfernt werden passiert gar nichts.

      Woran könnte das liegen?

    • Werden die übers ACP oder ein anderes Plugin hinzugefügt/entfernt?

    • über das ACP

    • Kleines Update: Wenn ich "Benutzer bearbeiten" eine Gruppe hinzufüge wird es direkt im Discord aktualisiert. Wenn ich die Gruppe wieder entferne bleibt die Discord Rolle aber weiterhin bestehen.

  • Ein Fehler ist aufgetreten

    Interner Fehlercode: 664a640843523c429e09b1d75a900f7927787748

    Was ist passiert?

    Leider ist es bei der Verarbeitung zu einem Fehler gekommen und die Ausführung wurde abgebrochen. Falls möglich, leiten Sie bitte den oben stehenden Fehlercode an den Administrator weiter.


    Administratoren können die vollständige Fehlermeldung mit Hilfe dieses Codes in der Administrationsoberfläche unter „Protokoll » Fehler“ einsehen. Zusätzlich wurden die Informationen in die Protokolldatei */log/2018-12-30.txt geschrieben und können beispielsweise mit Hilfe eines FTP-Programms abgerufen werden.


    Hinweis: Der Fehlercode wird zufällig generiert, erlaubt keinen Rückschluss auf die Ursache und ist daher für Dritte nutzlos.

    System Information

    • PHP Version:

      7.1.18

    • WoltLab Suite Core:

      3.0.18

    • Peak Memory Usage:

      42.525/1024 MiB

    • Request URI:

      /acp/index.php?install-package/&t=97da2ddbfd90ade1d1e8f50da12b7eb767a0fac7

    • Referrer:

      http://www.lpg-schwarze-pumpe-…tion-confirm/&queueID=356

    • User Agent:

      Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36

    Final Error

    • Error Type:

      wcf\system\database\exception\DatabaseQueryExecutionException

    • Error Message:

      Could not execute statement 'ALTER TABLE `wcf1_user` ADD COLUMN `discordUsername` varchar(50) DEFAULT NULL'

    • Error Code:

      42

    • File:

      */lib/system/database/statement/PreparedStatement.class.php (105)

    • Stack Trace:
      • #0 */lib/system/database/editor/MySQLDatabaseEditor.class.php (115):
      • wcf\system\database\statement\PreparedStatement->execute()
      • #1 */lib/system/database/util/SQLParser.class.php (237):
      • wcf\system\database\editor\MySQLDatabaseEditor->addColumn('wcf1_user', 'discordUsername', [ 6 items ])
      • #2 */lib/system/package/PackageInstallationSQLParser.class.php (289):
      • wcf\system\database\util\SQLParser->executeAddColumnStatement('wcf1_user', 'discordUsername', [ 6 items ])
      • #3 */lib/system/database/util/SQLParser.class.php (155):
      • wcf\system\package\PackageInstallationSQLParser->executeAddColumnStatement('wcf1_user', 'discordUsername', [ 6 items ])
      • #4 */lib/system/database/util/SQLParser.class.php (47):
      • wcf\system\database\util\SQLParser->executeStatement('ALTER TABLE', 'ALTER TABLE wcf1_user ADD discordUsername VARCHAR(50) NULL DEFAULT NULL')
      • #5 */lib/system/package/plugin/SQLPackageInstallationPlugin.class.php (74):
      • wcf\system\database\util\SQLParser->execute()
      • #6 */lib/system/package/PackageInstallationDispatcher.class.php (603):
      • wcf\system\package\plugin\SQLPackageInstallationPlugin->install()
      • #7 */lib/system/package/PackageInstallationDispatcher.class.php (141):
      • wcf\system\package\PackageInstallationDispatcher->executePIP([ attributes => , pip => , value => ])
      • #8 */lib/acp/action/InstallPackageAction.class.php (72):
      • wcf\system\package\PackageInstallationDispatcher->install('5b12eae5')
      • #9 */lib/action/AbstractDialogAction.class.php (68):
      • wcf\acp\action\InstallPackageAction->stepInstall()
      • #10 */lib/action/AbstractAction.class.php (47):
      • wcf\action\AbstractDialogAction->execute()
      • #11 */lib/system/request/Request.class.php (83):
      • wcf\action\AbstractAction->__run()
      • #12 */lib/system/request/RequestHandler.class.php (94):
      • wcf\system\request\Request->execute()
      • #13 */acp/index.php (9):
      • wcf\system\request\RequestHandler->handle('wcf', true)

    Original Error

    • Error Type:

      PDOException

    • Error Message:

      SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name 'discordUsername'

    • Error Code:

      42

    • File:

      */lib/system/database/statement/PreparedStatement.class.php (93)

    • Stack Trace:
      • #0 */lib/system/database/statement/PreparedStatement.class.php (93):
      • PDOStatement->execute([ ])
      • #1 */lib/system/database/editor/MySQLDatabaseEditor.class.php (115):
      • wcf\system\database\statement\PreparedStatement->execute()
      • #2 */lib/system/database/util/SQLParser.class.php (237):
      • wcf\system\database\editor\MySQLDatabaseEditor->addColumn('wcf1_user', 'discordUsername', [ 6 items ])
      • #3 */lib/system/package/PackageInstallationSQLParser.class.php (289):
      • wcf\system\database\util\SQLParser->executeAddColumnStatement('wcf1_user', 'discordUsername', [ 6 items ])
      • #4 */lib/system/database/util/SQLParser.class.php (155):
      • wcf\system\package\PackageInstallationSQLParser->executeAddColumnStatement('wcf1_user', 'discordUsername', [ 6 items ])
      • #5 */lib/system/database/util/SQLParser.class.php (47):
      • wcf\system\database\util\SQLParser->executeStatement('ALTER TABLE', 'ALTER TABLE wcf1_user ADD discordUsername VARCHAR(50) NULL DEFAULT NULL')
      • #6 */lib/system/package/plugin/SQLPackageInstallationPlugin.class.php (74):
      • wcf\system\database\util\SQLParser->execute()
      • #7 */lib/system/package/PackageInstallationDispatcher.class.php (603):
      • wcf\system\package\plugin\SQLPackageInstallationPlugin->install()
      • #8 */lib/system/package/PackageInstallationDispatcher.class.php (141):
      • wcf\system\package\PackageInstallationDispatcher->executePIP([ attributes => , pip => , value => ])
      • #9 */lib/acp/action/InstallPackageAction.class.php (72):
      • wcf\system\package\PackageInstallationDispatcher->install('5b12eae5')
      • #10 */lib/action/AbstractDialogAction.class.php (68):
      • wcf\acp\action\InstallPackageAction->stepInstall()
      • #11 */lib/action/AbstractAction.class.php (47):
      • wcf\action\AbstractDialogAction->execute()
      • #12 */lib/system/request/Request.class.php (83):
      • wcf\action\AbstractAction->__run()
      • #13 */lib/system/request/RequestHandler.class.php (94):
      • wcf\system\request\Request->execute()
      • #14 */acp/index.php (9):
      • wcf\system\request\RequestHandler->handle('wcf', true)
  • Hallo Hanashi,


    habe mit der aktuellsten Version, dass die Bans nicht synchronisiert werden. Gruppen/Benutzernamen werden synchronisiert, aber es wird bei einer Sperrung im Forum niemand aus dem Discord verbannt, obwohl der Bot "Administrator"-Rechte hat.


    Gruß

    • Hi, ist bereits bekannt. Siehe Supportforum.

  • Angelehnt an die letzten Post, wird es einen Fix dazu geben bzw eine Info über den derzeitigen Stand der Dinge.

    Das Plugin hat Potential !

    • Nehme alles zurück. Man muss leider etwas quer lesen und die geänderte Registrierung von Discord anwenden damit der Bot lauffähig ist. Eventuell nimmt der Entwickler die Änderung mit.


      Danke für das Plugin

    • Hi um was ging es?

    • Die Fehlerhafte Anleitung ;)

    • Ich kenne keine fehlerhafte Anleitung.

Customers Who Bought This File Also Bought

  1. Modern Shoutbox Pro

    New This plugin provides a clean and modern shoutbox for your community.
    WoltLab Cloud
    EUR 5.95
    • Like 292
    • 19k Downloads
    • 4.8k Purchases
  2. Community Bot

    • UdoZ
    • (6)
    New The 'Swiss Knife' for your community.
    EUR 9.97
    • Like 35
    • 2.7k Downloads
    • 908 Purchases
  3. An comfortable ticket system for reporting support tickets and software bugs.
    WoltLab Cloud
    EUR 39.95
    • Like 20
    • 2.1k Downloads
    • 631 Purchases
  4. The original Donation Plugin (Paypal, PSC, Bank Transfer)
    WoltLab Cloud
    EUR 19.99
    • Like 111
    • 6.1k Downloads
    • 1.4k Purchases