{"id":16265939,"url":"https://github.com/zernonia/swappy-one","last_synced_at":"2025-03-19T22:30:35.620Z","repository":{"id":45389813,"uuid":"434663207","full_name":"zernonia/swappy-one","owner":"zernonia","description":null,"archived":false,"fork":false,"pushed_at":"2021-12-22T01:39:49.000Z","size":309,"stargazers_count":31,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-17T11:21:32.011Z","etag":null,"topics":["holiday-hackdays","supabase","twitter","vercel","vite","vue","vueuse"],"latest_commit_sha":null,"homepage":"https://swappy.one","language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zernonia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-12-03T16:30:14.000Z","updated_at":"2024-11-03T15:00:51.000Z","dependencies_parsed_at":"2022-09-18T12:10:17.071Z","dependency_job_id":null,"html_url":"https://github.com/zernonia/swappy-one","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zernonia%2Fswappy-one","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zernonia%2Fswappy-one/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zernonia%2Fswappy-one/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zernonia%2Fswappy-one/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zernonia","download_url":"https://codeload.github.com/zernonia/swappy-one/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244515595,"owners_count":20464916,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["holiday-hackdays","supabase","twitter","vercel","vite","vue","vueuse"],"created_at":"2024-10-10T17:21:11.745Z","updated_at":"2025-03-19T22:30:35.266Z","avatar_url":"https://github.com/zernonia.png","language":"Vue","funding_links":["https://www.buymeacoffee.com/zernonia"],"categories":[],"sub_categories":[],"readme":"\u003c!-- PROJECT LOGO --\u003e\n\u003cbr /\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/zernonia/swappy-one\"\u003e\n    \u003cimg src=\"public/favicon.png\" alt=\"Logo\" width=\"80\" height=\"80\"\u003e\n  \u003c/a\u003e\n\n  \u003ch3 align=\"center\"\u003eSwappy.one\u003c/h3\u003e\n\n  \u003cp align=\"center\"\u003e\n  Simple \u0026 Fun project for \u003cstrong\u003e\u003ca href=\"https://supabase.io/\"\u003eSupabase\u003c/a\u003e Holiday Hackdays!\u003c/strong\u003e\n    \u003cbr /\u003e\n    Swap your Twitter image based on interest/season temporarily or forever!\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://swappy.one\"\u003eView Demo\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/zernonia/swappy-one/issues\"\u003eReport Bug\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/zernonia/swappy-one/issues\"\u003eRequest Feature\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n![Swappy.one](public/og.png)\n\n## 🚀 Features\n\n- 🎉 Add badges/frame to your Twitter profile\n- 🤩 Share templates with your friends to enjoy this festive season\n- 🔒 Only update your profile image\n- 🤚 Customize the placement of element yourself\n\n## 📇 About The Project\n\nThis project is inspired by Facebook's Temporary Profile Picture, as well as the Twitter Space's logo when someone is joining a Space. Thus, I've created this apps to swap your plain Twitter picture to fit the **season/event/anything** that you want your follower to notice!\n\nAfter a certain amount of period (you can configure on the app), it will automatically **swap back** (hence, Swappy) to your original image. And you can revisit the app when you feel like putting on another badges in the future.\n\n`Author: @zernonia`\n\n### 🔨 Built With\n\n- [Supabase](https://supabase.com/)\n- [Vue 3](https://v3.vuejs.org/)\n- [Vite](https://vitejs.dev/)\n- [WindiCSS](https://windicss.org/)\n\n### ⚡ Supabase Service\n\n- Supabase Database\n- Supabase Auth (Twitter)\n- Supabase Storage\n- Postgres Function\n\n### Postgres SQL\n\n1. Store user's history\n\n   ```sql\n   create or replace function public.handle_new_user_image()\n   returns trigger as $$\n   begin\n     insert into public.user_history (user_id, template, new_image_key)\n     values (new.id, new.template, new.new_image_key);\n     return new;\n   end;\n   $$ language plpgsql security definer;\n\n   create trigger on_new_user_image\n     after insert or update of update_on on public.user\n     for each row execute procedure public.handle_new_user_image();\n   ```\n\n2. Invoke Vercel serverless function\n\n   ```sql\n   create or replace function change_back_image_vercel_webhook (input_id uuid)\n     returns integer\n     language plpgsql\n     as\n     $$\n       begin\n         return (select\n           net.http_post(\n               url:='https://swappy.one/api/user/change_back_image',\n               body:=(\n                 select json_build_object(\n                   'id', a.id,\n                   'old_image_key', a.old_image_key,\n                   'token', a.oauth_token,\n                   'secret', a.oauth_token_secret\n                   ) as body\n                 from (select a.id, a.old_image_key, b.oauth_token , b.oauth_token_secret\n                   from public.user a inner join public.user_token b on a.id = b.user_id where a.id = input_id) a\n               )::jsonb\n           ) as request_id);\n       end;\n     $$\n   ```\n\n3. Function to query all the rows that need to change back their image, and loop through each row and call the `change_back_image_vercel_webhook`\n\n   ```sql\n   create or replace function check_date_and_change_back()\n     returns table (request_id int)\n     language plpgsql\n     as\n     $$\n       declare\n         r record;\n       begin\n         for r in (\n           select * from public.user\n           where now() \u003e change_back_date and changed_back = false\n         ) loop\n             request_id := change_back_image_vercel_webhook(r.id);\n             return next;\n           end loop;\n       end;\n     $$;\n   ```\n\n4. CRON job to start the function #3 every hour.\n\n   ```sql\n   create extension if not exists pg_cron;\n   grant usage on schema cron to postgres;\n   grant all privileges on all tables in schema cron to postgres;\n\n   select\n     cron.schedule(\n       'change_back_user_old_image',\n       '0 */1 * * *', -- “At minute 0 past every 1th hour.”  https://crontab.guru/#0_*/1_*_*_*\n       $$\n         select check_date_and_change_back()\n       $$\n     );\n   ```\n\n## 🌎 Local Development\n\n### Prerequisites\n\nYarn\n\n```sh\nnpm install --global yarn\n```\n\n### Development\n\n1. Clone the repo\n   ```sh\n   git clone https://github.com/zernonia/swappy-one.git\n   ```\n2. Install NPM packages\n   ```sh\n   yarn install\n   ```\n3. Create `.env`\n\n   ```bash\n    VITE_SUPABASE_URL=\n    VITE_SUPABASE_ANON_KEY=\n    VITE_SUPABASE_SERVICE_KEY=\n    VITE_TWITTER_CONSUMER_KEY=\n    VITE_TWITTER_CONSUMER_SECRET=\n    TWITTER_ACCESS_TOKEN_KEY=\n    TWITTER_ACCESS_TOKEN_SECRET=\n    VITE_TWITTER_BEARER_TOKEN=\n   ```\n\n4. Run Development instance\n   ```sh\n   vercel dev\n   ```\n\n## ➕ Contributing\n\nContributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the Branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n## 🙏 Acknowledgement\n\n1. Fundamental for this Visualization ([Generate database types from OpenAPI specification](https://supabase.io/docs/reference/javascript/generating-types#generate-database-types-from-openapi-specification))\n2. Guide to Construct Dynamic SVG Connector ([Connecting Table using SVG](https://codepen.io/alojzije/pen/ndfrI))\n3. [Icones - icon gallery](https://icones.js.org/)\n\n## 📜 License\n\nNot Associated with Supabase.\n\nDistributed under the MIT License. See `LICENSE` for more information.\n\n# 📧 Contact\n\nZernonia - [@zernonia](https://twitter.com/zernonia) - zernonia@gmail.com\n\nAlso, if you like my work, please buy me a coffee ☕😳\n\n\u003ca href=\"https://www.buymeacoffee.com/zernonia\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png\" alt=\"Logo\" \u003e\n  \u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzernonia%2Fswappy-one","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzernonia%2Fswappy-one","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzernonia%2Fswappy-one/lists"}