├── .env ├── .env.production ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md └── workflows │ ├── main2prod.yml │ └── prodtag.yml ├── .gitignore ├── .prettierrc ├── LICENSE ├── PRIVACY.MD ├── README.md ├── compose └── index.html ├── design ├── logo-2-avatar.png ├── logo-2.png ├── logo-2.svg ├── logo-3.png ├── logo-3.svg ├── logo-4.png ├── logo-4.svg ├── logo-bg-4.png ├── logo-bg-4.svg ├── logo-favicon-4.png ├── logo-text.svg ├── logo.afdesign ├── logo.png ├── logo.svg └── profile-banner.png ├── index.html ├── package-lock.json ├── package.json ├── public ├── 72.png ├── agora-social-desktop-1.png ├── agora-social-desktop-2.png ├── agora-social-desktop-3.png ├── agora-social-mobile-1.png ├── agora-social-mobile-2.png ├── agora-social-mobile-3.png ├── apple-touch-icon.png ├── favicon.ico ├── logo-192.png ├── logo-512.png ├── logo-badge-72.png ├── logo-maskable-512.png ├── og-image-2.jpg ├── og-image.png ├── robots.txt └── sw.js ├── readme-assets ├── boosts-carousel.jpg ├── fancy-screenshot.jpg ├── hashtag-stuffing-collapsing.jpg ├── thread-number-badge.jpg └── user-name-display.jpg ├── rollbar.js ├── scripts ├── extract-url.js ├── fetch-instances-list.js ├── fetch-lingva-languages.js └── fetch-supported-languages.js ├── src ├── app.css ├── app.jsx ├── assets │ ├── features │ │ ├── boosts-carousel.jpg │ │ ├── grouped-notifications.jpg │ │ ├── multi-column.jpg │ │ ├── multi-hashtag-timeline.jpg │ │ └── nested-comments-thread.jpg │ ├── floating-button.svg │ ├── logo-text.svg │ ├── logo.png │ ├── logo.svg │ ├── multi-column.svg │ ├── phanpy-bg.svg │ └── tab-menu-bar.svg ├── cloak-mode.css ├── components │ ├── AsyncText.jsx │ ├── account-block.css │ ├── account-block.jsx │ ├── account-info.css │ ├── account-info.jsx │ ├── account-sheet.jsx │ ├── avatar.css │ ├── avatar.jsx │ ├── background-service.jsx │ ├── columns.jsx │ ├── compose-button.jsx │ ├── compose.css │ ├── compose.jsx │ ├── drafts.css │ ├── drafts.jsx │ ├── emoji-text.jsx │ ├── follow-request-buttons.jsx │ ├── generic-accounts.css │ ├── generic-accounts.jsx │ ├── icon.jsx │ ├── keyboard-shortcuts-help.css │ ├── keyboard-shortcuts-help.jsx │ ├── link.jsx │ ├── list-add-edit.jsx │ ├── loader.css │ ├── loader.jsx │ ├── media-alt-modal.jsx │ ├── media-modal.jsx │ ├── media.jsx │ ├── menu-confirm.jsx │ ├── menu-link.jsx │ ├── menu2.jsx │ ├── modal.css │ ├── modal.jsx │ ├── modals.jsx │ ├── name-text.css │ ├── name-text.jsx │ ├── nav-menu.css │ ├── nav-menu.jsx │ ├── notification-service.jsx │ ├── notification.jsx │ ├── poll.jsx │ ├── relative-time.jsx │ ├── search-command.css │ ├── search-command.jsx │ ├── search-form.jsx │ ├── shortcuts-settings.css │ ├── shortcuts-settings.jsx │ ├── shortcuts.css │ ├── shortcuts.jsx │ ├── status.css │ ├── status.jsx │ ├── timeline.jsx │ ├── translation-block.css │ └── translation-block.jsx ├── compose.jsx ├── data │ ├── features.json │ ├── instances.json │ ├── lingva-source-languages.json │ ├── lingva-target-languages.json │ ├── status-supported-languages.json │ └── url-regex.json ├── index.css ├── main.jsx ├── pages │ ├── 404.jsx │ ├── account-statuses.jsx │ ├── accounts.css │ ├── accounts.jsx │ ├── bookmarks.jsx │ ├── favourites.jsx │ ├── filters.css │ ├── filters.jsx │ ├── followed-hashtags.jsx │ ├── following.jsx │ ├── forYou.jsx │ ├── hashtag.jsx │ ├── home.jsx │ ├── http-route.jsx │ ├── importFriends.jsx │ ├── importTwitter.jsx │ ├── list.jsx │ ├── lists.css │ ├── lists.jsx │ ├── login.css │ ├── login.jsx │ ├── mentions.jsx │ ├── notifications-menu.css │ ├── notifications.css │ ├── notifications.jsx │ ├── public.jsx │ ├── search.css │ ├── search.jsx │ ├── settings.css │ ├── settings.jsx │ ├── status-route.jsx │ ├── status.css │ ├── status.jsx │ ├── suggested-follows.jsx │ ├── topics.jsx │ ├── trending.css │ ├── trending.jsx │ ├── welcome.css │ └── welcome.jsx └── utils │ ├── api.js │ ├── auth.js │ ├── db.js │ ├── emojify-text.js │ ├── enhance-content.js │ ├── filters.jsx │ ├── focus-deck.jsx │ ├── get-instance-status-url.js │ ├── get-translate-target-language.jsx │ ├── getHTMLText.jsx │ ├── group-notifications.jsx │ ├── handle-content-links.js │ ├── html-content-length.js │ ├── isMastodonLinkMaybe.jsx │ ├── locale-match.jsx │ ├── localeCode2Text.jsx │ ├── mem.js │ ├── nice-date-time.js │ ├── open-compose.js │ ├── pmem.js │ ├── protocol-translator.js │ ├── push-notifications.js │ ├── safe-bounding-box-padding.js │ ├── shortcuts.js │ ├── shorten-number.jsx │ ├── show-toast.js │ ├── states.js │ ├── status-peek.jsx │ ├── store-utils.js │ ├── store.js │ ├── supports.js │ ├── timeline-utils.jsx │ ├── toast-alert.js │ ├── useInterval.js │ ├── useLocationChange.js │ ├── usePageVisibility.js │ ├── useScroll.js │ ├── useTitle.js │ ├── useTruncated.js │ ├── vibe-tag.js │ └── visibility-icons-map.js └── vite.config.js /.env: -------------------------------------------------------------------------------- 1 | VITE_CLIENT_NAME=Agora 2 | VITE_CLIENT_ID=app.agorasocial 3 | VITE_WEBSITE=https://agorasocial.app -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | VITE_APP_ENV=production -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | - Which instance: [e.g. mastodon.social] 13 | 14 | **To Reproduce** 15 | Steps to reproduce the behavior: 16 | 1. Go to '...' 17 | 2. Click on '....' 18 | 3. Scroll down to '....' 19 | 4. See error 20 | 21 | **Expected behavior** 22 | A clear and concise description of what you expected to happen. 23 | 24 | **Screenshots** 25 | If applicable, add screenshots to help explain your problem. 26 | 27 | **Desktop (please complete the following information):** 28 | - OS: [e.g. iOS] 29 | - Browser [e.g. chrome, safari] 30 | - Version [e.g. 22] 31 | 32 | **Smartphone (please complete the following information):** 33 | - Device: [e.g. iPhone6] 34 | - OS: [e.g. iOS8.1] 35 | - Browser [e.g. stock browser, safari] 36 | - Version [e.g. 22] 37 | 38 | **Additional context** 39 | Add any other context about the problem here. 40 | -------------------------------------------------------------------------------- /.github/workflows/main2prod.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request to `main` from `production` 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | auto-pull-request: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: vsoch/pull-request-action@master 13 | env: 14 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 15 | PULL_REQUEST_FROM_BRANCH: 'main' 16 | PULL_REQUEST_BRANCH: 'production' 17 | -------------------------------------------------------------------------------- /.github/workflows/prodtag.yml: -------------------------------------------------------------------------------- 1 | name: Auto-create tag/release on every push to `production` 2 | 3 | on: 4 | push: 5 | branches: 6 | - production 7 | 8 | jobs: 9 | tag: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | ref: production 17 | # - run: git tag "`date +%Y.%m.%d`.`git rev-parse --short HEAD`" $(git rev-parse HEAD) 18 | # - run: git push --tags 19 | - uses: actions/setup-node@v3 20 | with: 21 | node-version: 18 22 | - run: npm ci && npm run build 23 | - run: cd dist && zip -r ../phanpy-dist.zip . && cd .. 24 | - id: tag_name 25 | run: echo ::set-output name=tag_name::$(date +%Y.%m.%d).$(git rev-parse --short HEAD) 26 | - uses: softprops/action-gh-release@v1 27 | with: 28 | tag_name: ${{ steps.tag_name.outputs.tag_name }} 29 | generate_release_notes: true 30 | files: phanpy-dist.zip 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | # Custom 27 | .env.dev 28 | src/data/instances-full.json 29 | phanpy-dist.zip -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "useTabs": false, 4 | "singleQuote": true, 5 | "trailingComma": "all", 6 | "importOrder": [ 7 | "^[^.].*.css$", 8 | "index.css$", 9 | ".css$", 10 | "", 11 | "/assets/", 12 | "^../", 13 | "^[./]" 14 | ], 15 | "importOrderSeparation": true, 16 | "importOrderSortSpecifiers": true, 17 | "importOrderGroupNamespaceSpecifiers": true, 18 | "importOrderCaseInsensitive": true 19 | } 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Lim Chee Aun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PRIVACY.MD: -------------------------------------------------------------------------------- 1 | # Privacy Policy 2 | 3 | Agora does not collect or process any personal information from its users. The website is used to connect to third-party Mastodon servers that may or may not collect personal information and are not covered by this privacy policy. Each third-party Mastodon server comes equipped with its own privacy policy that can be viewed through that server's website. 4 | 5 | ## Hosting 6 | 7 | Agora is hosted on [Vercel](https://vercel.com) as a static website. Read more about [Vercel's privacy policy](https://vercel.com/legal/privacy-policy). 8 | 9 | ## Post translations 10 | 11 | Agora uses [Lingva Translate](https://github.com/thedaviddelta/lingva-translate) to translate posts. 12 | 13 | ## Error logging 14 | 15 | Agora dev site (*dev.Agora.social*) uses [Rollbar](https://rollbar.com/) to log errors for debugging purposes. Read more about [Rollbar's privacy policy](https://rollbar.com/privacy/). The production site (*Agora.social*) does not use error logging. 16 | -------------------------------------------------------------------------------- /compose/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Compose / %VITE_CLIENT_NAME% 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /design/logo-2-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/design/logo-2-avatar.png -------------------------------------------------------------------------------- /design/logo-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/design/logo-2.png -------------------------------------------------------------------------------- /design/logo-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/design/logo-3.png -------------------------------------------------------------------------------- /design/logo-3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /design/logo-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/design/logo-4.png -------------------------------------------------------------------------------- /design/logo-4.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /design/logo-bg-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/design/logo-bg-4.png -------------------------------------------------------------------------------- /design/logo-bg-4.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /design/logo-favicon-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/design/logo-favicon-4.png -------------------------------------------------------------------------------- /design/logo-text.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /design/logo.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/design/logo.afdesign -------------------------------------------------------------------------------- /design/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/design/logo.png -------------------------------------------------------------------------------- /design/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /design/profile-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/design/profile-banner.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | %VITE_CLIENT_NAME% 10 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | Mastodon 42 | 43 | 44 |
45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "agora", 3 | "version": "0.1.0", 4 | "type": "module", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "fetch-instances": "env $(cat .env.dev | grep -v \"#\" | xargs) node scripts/fetch-instances-list.js", 10 | "sourcemap": "npx source-map-explorer dist/assets/*.js" 11 | }, 12 | "dependencies": { 13 | "@atproto/api": "^0.12.22", 14 | "@formatjs/intl-localematcher": "~0.4.2", 15 | "@formkit/auto-animate": "~0.8.0", 16 | "@github/text-expander-element": "~2.5.0", 17 | "@iconify-icons/mingcute": "~1.2.8", 18 | "@justinribeiro/lite-youtube": "~1.5.0", 19 | "@storedotapp/pwa-install-dialog": "^1.1.2", 20 | "@szhsin/react-menu": "~4.1.0", 21 | "@uidotdev/usehooks": "~2.4.0", 22 | "@vercel/analytics": "^1.1.2", 23 | "common-words": "^0.1.3", 24 | "dayjs": "~1.11.10", 25 | "dayjs-twitter": "~0.5.0", 26 | "fast-blurhash": "~1.1.2", 27 | "fast-deep-equal": "~3.1.3", 28 | "fedialgo": "github:ghobs91/fedialgo", 29 | "idb-keyval": "~6.2.1", 30 | "just-debounce-it": "~3.2.0", 31 | "lz-string": "~1.5.0", 32 | "masto": "~6.3.1", 33 | "moize": "~6.1.6", 34 | "nostr-tools": "^2.5.0", 35 | "p-retry": "~6.1.0", 36 | "p-throttle": "~5.1.0", 37 | "preact": "~10.18.1", 38 | "react-hotkeys-hook": "~4.4.1", 39 | "react-intersection-observer": "~9.5.2", 40 | "react-quick-pinch-zoom": "~5.0.0", 41 | "react-router-dom": "6.6.2", 42 | "sanitize-html": "^2.12.1", 43 | "string-length": "5.0.1", 44 | "swiped-events": "~1.1.7", 45 | "toastify-js": "~1.12.0", 46 | "uid": "~2.0.2", 47 | "use-debounce": "~9.0.4", 48 | "use-long-press": "~3.2.0", 49 | "use-resize-observer": "~9.1.0", 50 | "valtio": "1.9.0" 51 | }, 52 | "devDependencies": { 53 | "@iconify/react": "^4.1.1", 54 | "@preact/preset-vite": "~2.6.0", 55 | "@trivago/prettier-plugin-sort-imports": "~4.2.0", 56 | "postcss": "~8.4.31", 57 | "postcss-dark-theme-class": "~1.0.0", 58 | "postcss-preset-env": "~9.2.0", 59 | "twitter-text": "~3.1.0", 60 | "vite": "~4.4.11", 61 | "vite-plugin-generate-file": "~0.0.4", 62 | "vite-plugin-html-config": "~1.0.11", 63 | "vite-plugin-pwa": "~0.16.5", 64 | "vite-plugin-remove-console": "~2.1.1", 65 | "workbox-cacheable-response": "~7.0.0", 66 | "workbox-expiration": "~7.0.0", 67 | "workbox-routing": "~7.0.0", 68 | "workbox-strategies": "~7.0.0" 69 | }, 70 | "postcss": { 71 | "plugins": { 72 | "postcss-dark-theme-class": {}, 73 | "postcss-preset-env": { 74 | "features": { 75 | "logical-properties-and-values": false 76 | } 77 | } 78 | } 79 | }, 80 | "browserslist": [ 81 | "defaults", 82 | "android >= 4" 83 | ] 84 | } 85 | -------------------------------------------------------------------------------- /public/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/72.png -------------------------------------------------------------------------------- /public/agora-social-desktop-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/agora-social-desktop-1.png -------------------------------------------------------------------------------- /public/agora-social-desktop-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/agora-social-desktop-2.png -------------------------------------------------------------------------------- /public/agora-social-desktop-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/agora-social-desktop-3.png -------------------------------------------------------------------------------- /public/agora-social-mobile-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/agora-social-mobile-1.png -------------------------------------------------------------------------------- /public/agora-social-mobile-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/agora-social-mobile-2.png -------------------------------------------------------------------------------- /public/agora-social-mobile-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/agora-social-mobile-3.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/favicon.ico -------------------------------------------------------------------------------- /public/logo-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/logo-192.png -------------------------------------------------------------------------------- /public/logo-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/logo-512.png -------------------------------------------------------------------------------- /public/logo-badge-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/logo-badge-72.png -------------------------------------------------------------------------------- /public/logo-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/logo-maskable-512.png -------------------------------------------------------------------------------- /public/og-image-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/og-image-2.jpg -------------------------------------------------------------------------------- /public/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/public/og-image.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow: / -------------------------------------------------------------------------------- /readme-assets/boosts-carousel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/readme-assets/boosts-carousel.jpg -------------------------------------------------------------------------------- /readme-assets/fancy-screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/readme-assets/fancy-screenshot.jpg -------------------------------------------------------------------------------- /readme-assets/hashtag-stuffing-collapsing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/readme-assets/hashtag-stuffing-collapsing.jpg -------------------------------------------------------------------------------- /readme-assets/thread-number-badge.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/readme-assets/thread-number-badge.jpg -------------------------------------------------------------------------------- /readme-assets/user-name-display.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghobs91/Agora/a7867776b65f002f6b514dea490d675b76744472/readme-assets/user-name-display.jpg -------------------------------------------------------------------------------- /scripts/extract-url.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import regexSupplant from 'twitter-text/dist/lib/regexSupplant.js'; 3 | import validDomain from 'twitter-text/dist/regexp/validDomain.js'; 4 | import validPortNumber from 'twitter-text/dist/regexp/validPortNumber.js'; 5 | import validUrlPath from 'twitter-text/dist/regexp/validUrlPath.js'; 6 | import validUrlPrecedingChars from 'twitter-text/dist/regexp/validUrlPrecedingChars.js'; 7 | import validUrlQueryChars from 'twitter-text/dist/regexp/validUrlQueryChars.js'; 8 | import validUrlQueryEndingChars from 'twitter-text/dist/regexp/validUrlQueryEndingChars.js'; 9 | 10 | // The difference with twitter-text's extractURL is that the protocol isn't 11 | // optional. 12 | 13 | const urlRegex = regexSupplant( 14 | '(' + // $1 total match 15 | '(#{validUrlPrecedingChars})' + // $2 Preceeding chracter 16 | '(' + // $3 URL 17 | '(https?:\\/\\/)' + // $4 Protocol (optional) <-- THIS IS THE DIFFERENCE, MISSING '?' AFTER PROTOCOL 18 | '(#{validDomain})' + // $5 Domain(s) 19 | '(?::(#{validPortNumber}))?' + // $6 Port number (optional) 20 | '(\\/#{validUrlPath}*)?' + // $7 URL Path 21 | '(\\?#{validUrlQueryChars}*#{validUrlQueryEndingChars})?' + // $8 Query String 22 | ')' + 23 | ')', 24 | { 25 | validUrlPrecedingChars, 26 | validDomain, 27 | validPortNumber, 28 | validUrlPath, 29 | validUrlQueryChars, 30 | validUrlQueryEndingChars, 31 | }, 32 | 'gi', 33 | ); 34 | 35 | const filePath = 'src/data/url-regex.json'; 36 | fs.writeFile( 37 | filePath, 38 | JSON.stringify({ 39 | source: urlRegex.source, 40 | flags: urlRegex.flags, 41 | }), 42 | (err) => { 43 | if (err) { 44 | console.error(err); 45 | } 46 | console.log(`Wrote ${filePath}`); 47 | }, 48 | ); 49 | -------------------------------------------------------------------------------- /scripts/fetch-instances-list.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | 3 | const { INSTANCES_SOCIAL_SECRET_TOKEN } = process.env; 4 | 5 | const params = new URLSearchParams({ 6 | count: 0, 7 | min_users: 500, 8 | sort_by: 'active_users', 9 | sort_order: 'desc', 10 | }); 11 | 12 | const url = `https://instances.social/api/1.0/instances/list?${params.toString()}`; 13 | const results = await fetch(url, { 14 | headers: { 15 | Authorization: `Bearer ${INSTANCES_SOCIAL_SECRET_TOKEN}`, 16 | }, 17 | }); 18 | 19 | const json = await results.json(); 20 | 21 | // Filters 22 | json.instances = json.instances.filter( 23 | (instance) => Number(instance.connections) > 20, 24 | ); 25 | 26 | const names = json.instances.map((instance) => instance.name); 27 | 28 | // Write to file 29 | const path = './src/data/instances.json'; 30 | fs.writeFileSync(path, JSON.stringify(names, null, '\t'), 'utf8'); 31 | 32 | // Write everything to file, for debugging 33 | const path2 = './src/data/instances-full.json'; 34 | fs.writeFileSync(path2, JSON.stringify(json, null, '\t'), 'utf8'); 35 | -------------------------------------------------------------------------------- /scripts/fetch-lingva-languages.js: -------------------------------------------------------------------------------- 1 | // Fetch https://lingva.ml/api/v1/languages/{source|target} 2 | import fs from 'fs'; 3 | 4 | fetch('https://lingva.ml/api/v1/languages/source') 5 | .then((response) => response.json()) 6 | .then((json) => { 7 | const file = './src/data/lingva-source-languages.json'; 8 | console.log(`Writing ${file}...`); 9 | fs.writeFileSync(file, JSON.stringify(json.languages, null, '\t'), 'utf8'); 10 | }); 11 | 12 | fetch('https://lingva.ml/api/v1/languages/target') 13 | .then((response) => response.json()) 14 | .then((json) => { 15 | const file = './src/data/lingva-target-languages.json'; 16 | console.log(`Writing ${file}...`); 17 | fs.writeFileSync(file, JSON.stringify(json.languages, null, '\t'), 'utf8'); 18 | }); 19 | -------------------------------------------------------------------------------- /scripts/fetch-supported-languages.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | 3 | const url = 'https://mastodon.social/'; 4 | 5 | const html = await fetch(url).then((res) => res.text()); 6 | 7 | // Extract the JSON between 8 | const json = html.match( 9 | /