Compare commits

..

348 Commits
dev ... master

Author SHA1 Message Date
b52d384152 Refactor: convert ERB to HAML, optionally associations, simplify navigation and views 2026-07-30 22:11:43 -07:00
ef3cffb107 Upgrade ruby 3.2.2 to 3.4.3 and rails 7 to 8 2025-04-24 03:49:24 -07:00
0e09bded3f Add czechers checkers concept page 2025-03-27 20:54:39 +00:00
c74323a855 Update git url 2025-03-27 20:53:06 +00:00
41506fa3e9 Add swipable delete to all doodads on index 2025-03-27 16:59:13 +00:00
e9e684f67d Use safer identity args for dfx 2024-07-18 15:03:39 +00:00
901b4bab5e Disable Delayed Job scheduler and Telegram bots 2024-06-24 09:52:17 +00:00
87bb7bb12f Remove index sums 2024-06-03 23:09:16 +00:00
7c828d9799 Fix icpswap pool index parser 2024-05-22 05:57:20 +00:00
00dcf1c6e5 Require login to add tokens 2024-04-20 02:42:23 +00:00
3525a35c36 Add swipe delete global doodads 2024-03-26 15:09:03 +00:00
bf118277f3 Update metapurse policies for private 2024-03-25 17:57:17 +00:00
74403c0ee2 Add tendy to default metapurse data 2024-03-25 15:27:47 +00:00
afe858ade9 Add private metapurse for users 2024-03-25 14:59:01 +00:00
4ae78edc49 Allow anon controlled metapurses 2024-03-25 13:59:35 +00:00
49883bcdbf Add default data values for new MetaPurse 2024-03-25 13:42:02 +00:00
3f3cee4df8 Add data view to metapurses 2024-03-25 13:26:28 +00:00
042c07f026 Adds ICP price support from binance for MetaPurse 2024-03-25 12:54:43 +00:00
75cfd7c4c0 Show price in metapurse 2024-03-14 04:28:17 +00:00
0c75a358fd Canister feature admins only 2024-03-11 02:47:33 +00:00
0cb2fb1dce UI match permissions 2024-03-10 23:47:59 +00:00
d68b1f8025 Add placeholder text. Simple rescues 2024-03-10 23:38:10 +00:00
12193503c2 Fix Metapurse total. Use number with delimiter 2024-03-10 13:54:47 +00:00
331389d8eb Try rescue broken metapurse 2024-03-10 13:46:34 +00:00
80c0c5d882 Add Metapurse total value 2024-03-10 13:45:58 +00:00
0639740344 Disable devise recoverable user email recovery 2024-03-10 13:13:32 +00:00
3719c7acf9 Add Metapurse 2024-03-10 13:08:14 +00:00
92b65a9101 Add token table association 2024-03-08 04:36:08 +00:00
448fa1a0b3 Add seed tokens 2024-02-08 16:57:34 +00:00
977214d102 Add refresh method to Token model 2024-02-08 16:57:27 +00:00
d720367521 Improve post delete style 2024-02-08 15:56:59 +00:00
f4148602a3 Update dev port 2024-02-08 15:54:12 +00:00
c386d5b271 Bug fix for when transfer_fee nil 2023-12-21 15:19:46 +00:00
94deb14d7e Limit token launch policy 2023-12-14 18:28:40 +00:00
ddf50b8266 Add start to Token creation feature 2023-12-09 05:27:08 +00:00
015e6dc520 Bugfix dip20 logo fetch 2023-12-08 11:07:21 +00:00
50b2d3c666 Add dip20 holder count and improve token show style 2023-12-08 10:48:09 +00:00
a6ddfcac24 Improve style of seats show display name above sit button 2023-12-06 15:23:23 +00:00
1faee1d530 Enable tables and seats 2023-12-06 13:03:36 +00:00
cb38b5ad8a Update capistrano puma 2023-12-06 12:53:53 +00:00
3725b7a476 Add todo push notifications 2023-12-06 08:48:49 +00:00
1f7ea47d1f Improve room index headline style 2023-12-05 10:59:18 +00:00
1e2d55e02e Pundit authorization sitewide 2023-12-05 10:55:29 +00:00
5dfcab4538 Update to puma 6 2023-12-04 20:50:51 +00:00
14a5fb5a10 Remove uglifier 2023-12-04 19:17:41 +00:00
7c12582387 Config uglifier 2023-12-04 19:09:04 +00:00
b8f7e56aa9 Config uglifier 2023-12-04 19:02:45 +00:00
d7b0d832bd Update puma gem 2023-12-04 17:30:57 +00:00
37fd707b24 Remove prodcution puma config to use default 2023-12-04 16:59:49 +00:00
7410fb8f03 Add 1 puma worker 2023-12-04 16:36:50 +00:00
d1f1fbbfc2 Add production puma config to repo 2023-12-04 16:21:56 +00:00
8eaeb04afa Update config for Rails 7 2023-12-04 16:00:28 +00:00
d7ed683dbe Improve Send Message button text 2023-12-04 12:44:12 +00:00
2d5f08fc49 Upgrade to ruby 3.2.2 2023-12-04 12:42:40 +00:00
1df60730f3 Bundle update 2023-12-04 12:06:30 +00:00
1962224aae Trying rails 6.1 config 2023-12-04 12:05:31 +00:00
dae38f52d0 Remove old uri version from gemfile 2023-12-04 12:02:53 +00:00
fadc9b230b Try old config setting for bugfix 2023-12-04 11:59:25 +00:00
a3fb1a22fc Add net-http gem for bugfix 2023-12-04 11:52:11 +00:00
76d392998e Upgrade config for Rails 7 2023-12-04 10:33:27 +00:00
9388c87477 Refine permissions and style 2023-12-04 10:10:55 +00:00
a59ab6cf03 Add Messages to Rooms 2023-12-04 09:37:57 +00:00
c583ee7f32 Add Chat Rooms with Turbo 2023-12-04 08:27:21 +00:00
6480644923 Upgrade to rails 7 2023-12-03 16:22:44 +00:00
eeced4eccb Rename Rooms to VideoRooms 2023-12-03 16:02:27 +00:00
e18cd8c76d Add Command scaffold and bot join table 2023-12-03 13:16:27 +00:00
363986d4fd Add TelegramWallet to bots 2023-12-02 16:32:39 +00:00
dd9872bd4a Add basic Telegram ICP wallet 2023-12-01 18:59:50 +00:00
499e46a468 Fix deprecated Pundit import syntax 2023-12-01 18:09:09 +00:00
58da926c87 Add telegram subscriber ids to Bots 2023-11-29 18:08:16 +00:00
de3cffbc9e Add gem capistrano3-delayed-job 2023-11-29 13:39:08 +00:00
44f75490a0 Add ActiveJob to start telegram bots 2023-11-29 13:27:03 +00:00
11077b1dc4 Add bots scaffold 2023-11-28 12:04:44 +00:00
e920a8feb9 Style improve nav spacing 2023-11-26 11:32:29 +00:00
bbb152fa5d Add micropost form to project show view 2023-11-26 10:09:55 +00:00
e5ad663e50 dev env title 2023-11-24 04:18:52 +00:00
60318bdbf5 Remove padding from headline 2023-11-24 04:12:22 +00:00
1cfc23a683 Contain own posts 2023-11-24 04:11:43 +00:00
f9ad8257f2 Add padding to contain 2023-11-24 04:10:01 +00:00
067af6f877 Anon user name 2023-11-23 14:49:46 +00:00
28ed4c1a86 Improve nav wallet style 2023-11-22 12:45:48 +00:00
de5961e602 Bugfix feed error 2023-11-22 12:38:20 +00:00
cc102a5e2b Bugfix global doodad footer template rendering 2023-11-22 12:24:45 +00:00
0114233f59 Add global property to Doodads 2023-11-22 12:11:12 +00:00
24e346ce60 Use polymorphic relationships for followable 2023-11-21 17:19:33 +00:00
e13ba15989 Improve feed 2023-11-21 14:59:40 +00:00
3418d9b7d1 Move files for bugfix 2023-11-21 12:46:14 +00:00
ba7aa67f07 Little style upgrade 2023-11-21 12:03:52 +00:00
3368617fb3 Add microposts to projects 2023-11-21 11:57:29 +00:00
768f89eecf Improve public home routes 2023-11-21 09:32:24 +00:00
f3739754b5 Style microposts 2023-11-21 09:26:09 +00:00
40438b4ea4 Improve style and routes 2023-11-20 15:40:51 +00:00
cf22312f2d Include followed profile posts in feed 2023-11-20 15:40:22 +00:00
3a18d741c2 Quickfix micropost feed and policy 2023-11-15 16:23:23 +00:00
3ba380e63b Fix unauthenticated route 2023-11-15 16:16:11 +00:00
669df703aa Make microposts polymorphic for profiles and users 2023-11-15 16:11:32 +00:00
e8d66e5243 Add post feed 2023-11-15 13:05:07 +00:00
e999470b72 Add microposts 2023-11-15 12:30:47 +00:00
e8599242ee Exploratory dev custom host. Prep reintro of thirteen tien len 2023-11-14 15:39:55 +00:00
d3481526a2 Use Anton font 2023-11-14 15:19:03 +00:00
65e68b3555 Improve profile style 2023-11-12 12:05:04 +00:00
35fbf649fe Improve token index style 2023-11-12 07:37:09 +00:00
2936cb33e1 Improve token index style 2023-11-12 06:21:52 +00:00
4bd3fdb361 Bugfix doodad user owner now optional 2023-11-12 06:10:56 +00:00
9879c8d239 Fix home page doodad overflow 2023-11-12 05:58:37 +00:00
a155b83a1b Add follow / unfollow button 2023-11-11 17:32:29 +00:00
6ab972ed38 Save data as float not int 2023-11-11 16:59:47 +00:00
4ff1dcf179 Improved display format for transfer fee 2023-11-11 16:38:48 +00:00
0319932f28 Improve ux link token logo to token show page 2023-11-11 16:29:08 +00:00
9f48f3aaa9 Smaller Token index font 2023-11-11 16:27:24 +00:00
9b20545578 Fix token logo url parser 2023-11-11 16:21:32 +00:00
6f24e84a25 Fix token transfer fee parse 2023-11-11 16:08:36 +00:00
3e589b4a26 Improve token logo widths 2023-11-11 16:07:43 +00:00
0dc4fc1121 Improve token index style 2023-11-11 15:58:14 +00:00
138d6050db Refresh token upon creation, allow delete 2023-11-11 15:06:47 +00:00
3bf5a82e86 Add basic icrc1 standard token parsing 2023-11-11 15:00:17 +00:00
5cdc00206c Add basic token canister parsing 2023-11-11 14:18:38 +00:00
a71010bf9f Add basics of Follower feature 2023-11-11 11:34:52 +00:00
fd0c70f217 Improve style make the text pop 2023-11-11 10:28:45 +00:00
19f416e9b7 Improve style 2023-11-09 17:54:40 +00:00
049149fd28 Improve style 2023-11-08 17:56:30 +00:00
afcadd2a26 Improve profile style 2023-11-08 17:38:38 +00:00
22bcbb5961 Fix long wallet id breaking mobile style 2023-11-08 16:17:06 +00:00
a430b41c8a Add DSCVR logo to social links 2023-11-08 13:57:44 +00:00
5495f38ae2 Social links formatting and style 2023-11-08 13:24:56 +00:00
8d89ff9cc0 Style profile show 2023-11-08 07:19:12 +00:00
adee6dcfd6 Style social links 2023-11-08 06:50:08 +00:00
9836aab757 Style profile headline 2023-11-08 06:29:31 +00:00
d04ff35533 Add icons to social links 2023-11-08 06:20:58 +00:00
5a4f314aab Add social links to profiles 2023-11-07 16:50:08 +00:00
a8fea8314f Style profile index 2023-11-07 04:09:00 +00:00
a7f01374fd Add user profiles 2023-11-06 17:21:23 +00:00
5f0658b750 Create basic User index show 2023-11-06 05:21:19 +00:00
02bd25b724 Improve textarea style 2023-10-29 11:20:56 +00:00
2b62269638 Fix token auth vs policy bug 2023-10-27 07:15:29 +00:00
c66ba3caac Allow public new doodad 2023-10-27 06:46:24 +00:00
32013a4e51 Rename Home to Public 2023-10-27 06:17:22 +00:00
cd83e39d64 Allow function in production 2023-10-27 06:10:31 +00:00
eb0a131403 Add token links in footer 2023-10-27 06:00:16 +00:00
39d1a5d6f9 Hide Add Canister button 2023-10-27 04:59:08 +00:00
0105134a7f Add Token scaffold 2023-10-27 04:50:02 +00:00
bf0e558bdd Improve style 2023-10-27 04:47:29 +00:00
bdf63fbbd9 Merge branch 'add-peetreon-projects' 2023-10-26 04:45:06 +00:00
2fc6245a50 Add project scaffold 2023-10-26 01:34:10 +00:00
dccc356561 Add project scaffold 2023-10-26 01:18:42 +00:00
2d0b3205d9 Add turbo frame for wallet balance 2023-10-25 02:00:34 +00:00
929c98bb14 Add webrtc chat 2023-10-23 06:58:18 +00:00
43a71faddf Upgrade to Rails 6 2023-10-23 01:46:50 +00:00
79b3b21aba Enable private doodads 2023-10-14 23:58:44 +00:00
c661d85727 Fix icy pepe eyecandy replace svg with png 2023-10-11 21:49:50 +00:00
f098c7b529 Hide wallet balance because too slow 2023-10-10 17:07:43 +00:00
a96ed295e4 Add eth balance to navigation wallet 2023-09-29 18:08:59 +00:00
0d3d2ed5b0 Add doodads 2023-09-29 17:59:13 +00:00
59fb2ab3e6 Rebrand to My Tendy Zone 2023-09-24 14:10:37 +00:00
145b63551d Fix typo 2023-09-24 13:43:22 +00:00
28c41a0c6b Update Gemfile.lock 2023-09-24 09:53:07 +00:00
3fb775fa35 Improve UI eyecandy rebrand to My Tendy Zone 2023-09-24 09:50:53 +00:00
cd6914198b Disable turbolinks 2023-09-24 09:50:24 +00:00
a71e4523d1 Add Canister scaffold 2023-09-24 09:49:42 +00:00
f621b90bd9 Add csrf header 2023-09-18 19:03:13 +00:00
184f26718b Fix doctype html 2023-09-18 18:08:24 +00:00
2fc656c053 Disable csrf to debug 2023-09-18 18:01:45 +00:00
47d63306ba Add redis gem 2023-09-18 17:53:08 +00:00
824795f620 Add domain to action cable allow list 2023-09-18 17:19:59 +00:00
6063b3e083 Fix videocall react cable 2023-09-18 15:37:33 +00:00
46fa3c712d Custom home page per domain 2023-09-17 17:53:14 +00:00
d7ed50c5a4 Fix react videochat component 2023-09-17 17:23:03 +00:00
b378f2a93d Update todo 2023-08-11 14:13:42 +00:00
cf45d8c38c Troubleshooting video chat component 2023-08-11 14:06:43 +00:00
108d5882a5 Update component name from App to VideoCall 2023-08-11 13:30:11 +00:00
c568d35d47 Update uglifier config 2023-08-11 13:27:14 +00:00
18d386a337 Update video chat code 2023-08-11 13:24:12 +00:00
c37157781f Add video chat 2023-08-11 12:45:59 +00:00
327028f3a3 Add source for video chat feature 2023-08-11 11:50:39 +00:00
f064add019 Reenable icypee nft logo eyecandy 2023-07-27 06:32:31 +00:00
48356ecd3b Pay winner ICYPEES rewards 2023-07-26 00:38:01 +00:00
9445656565 Hide soft token 2023-07-20 18:46:01 +00:00
b63246e6f6 Update deploy config 2023-07-20 18:34:44 +00:00
e2e1741a1c Show soft token in seat 2023-07-20 18:28:49 +00:00
924e514ad2 Remove hotfix to make admin 2023-07-20 18:18:42 +00:00
799b8e4ae6 Hotfix to make admin 2023-07-20 18:17:13 +00:00
3c24b0212a Hotfix to make admin 2023-07-20 18:15:28 +00:00
60435e06a9 Hotfix to make admin 2023-07-20 18:09:28 +00:00
d2eb76b855 Add wallet principal to user and player 2023-07-09 13:39:39 +00:00
b7576482c9 Landing page eyecandy improve 2023-07-08 08:57:05 +00:00
0db111a43d Add music video 2023-05-10 15:25:10 +00:00
b806737181 Add Icy Pepe NFT svg to eyecandy 2023-05-10 14:23:37 +00:00
0620472638 Add private urls to tables 2023-05-10 14:15:43 +00:00
b1c6ef71ed Remove skyspaces frame 2023-05-06 14:02:44 +00:00
4eae32da35 Add skyspaces frame 2023-05-05 06:44:36 +00:00
0a017b6197 Adds GONGO to home screen eyecandy 2023-05-02 11:51:01 +00:00
b1640e25ce Improve home page eyecandy 2023-04-30 12:29:35 +00:00
d8cde29c81 Add livereload to guard 2023-04-30 10:13:54 +00:00
1dbd9c887a Increase size of floating coin eyecandy 2023-04-30 06:53:22 +00:00
d9645d990c Add eyecandy bouncing coins 2023-04-29 15:24:12 +00:00
8e2cbb6146 Improve style of telegram link 2023-04-29 13:24:20 +00:00
468268c049 Add google font Anton similar to Impact 2023-04-29 12:43:54 +00:00
c684832726 Improve style 2023-04-29 12:33:37 +00:00
163f681fa1 Add telegram link 2023-04-29 11:08:36 +00:00
950f487a9c Add bort policy 2023-04-28 18:12:20 +00:00
d0aef1f0fb Hide user email domain 2023-04-28 18:12:09 +00:00
ac4285ac15 Add pundit authorization policies 2023-04-28 17:59:23 +00:00
986664ca82 Improve player inventory UI 2023-04-28 10:22:57 +00:00
19a450b1fe Ignore vim undo files 2023-04-28 10:22:27 +00:00
301830323f Update deploy config 2023-04-28 10:21:57 +00:00
d7ceb08d53 upgrade ruby 2023-04-03 14:59:55 +00:00
63a9cf946b Update ruby version 2023-03-25 16:07:26 +00:00
feba35eb43 Upgrade ruby 2022-05-24 11:26:36 -07:00
ae03f0720f Suited run spec 2022-05-20 23:12:55 -07:00
af4e97e102 Fix tests for new seat order 2021-12-18 23:28:11 -08:00
54eccc469a Remove sleep deprecated race condition workaround 2021-12-18 23:06:10 -08:00
2d8972a9cd Add instructions for dev env setup 2021-12-10 07:18:29 -08:00
eb21f11bcb Disable react 2021-12-06 01:42:39 -08:00
6ccbc22cb2 Add qr code to table 2021-11-27 00:21:55 -08:00
47939d6590 Add ideas for new tests 2021-11-21 02:08:29 -08:00
5563194cac Disable confirmation dialogs 2021-11-21 02:08:09 -08:00
c237a03316 Enable ajax loads 2021-11-20 07:46:32 -08:00
86ca66d02f Add sloppy ajax loading of game plays 2021-11-20 04:07:58 -08:00
89cd4d9795 Fix play order 2021-11-20 04:07:25 -08:00
01e4bbcf1e Fix Play Now button 2021-11-20 04:06:53 -08:00
570f5ee176 Fix display if player to beat is removed 2021-11-20 03:04:17 -08:00
0bfa0cd003 Merge pull request 'Fix winner check' (#1) from fix-winner-check into master
Reviewed-on: #1
2021-11-20 02:31:40 -08:00
dd94041ead Fix winner check 2021-11-20 01:48:58 -08:00
336ba03e13 Add auto play for bots 2021-11-20 00:09:01 -08:00
adb8d2fa92 Add seat management fix new game button 2021-11-17 07:56:39 -08:00
bdce615cac Change selected card style 2021-11-17 07:54:43 -08:00
4d81e9e076 Update default secret values 2021-11-16 06:53:56 -08:00
35552c1e1f Disabled control buttons when not in control 2021-11-15 18:54:38 -08:00
df66a535d8 Add about page with attributions 2021-11-13 17:29:01 -08:00
d728b2b85d Update git repo url 2021-11-13 17:28:22 -08:00
436b227600 Update deploy config 2021-11-13 02:29:34 -08:00
90c2f3172d Update deploy config 2021-11-13 01:26:53 -08:00
2a088661a1 Create button to remove bots 2021-11-10 22:14:43 -08:00
72a26675b5 Method must return boolean, not nil 2021-11-10 21:36:11 -08:00
bd76b33038 Add Bot button respects seat occupied status 2021-11-10 21:24:15 -08:00
3ee699aa4d Add more tests for Bots 2021-11-08 22:56:53 -08:00
27af043720 Silence deprecation warnings because factory_girl 2021-11-08 22:13:41 -08:00
ab42853cc1 Avoid js driver 2021-11-08 21:49:31 -08:00
ef1704d24c Adds Bot button and start of Bot Players 2021-11-07 21:48:48 -08:00
cbcd4caaea Use spring in test env 2021-11-07 21:47:37 -08:00
a056762208 Use spring gem to speed up dev testing 2021-11-06 23:09:16 -07:00
1627be37ce Fix failing tests 2021-11-05 22:37:14 -07:00
041f7c6163 Test click confirm 2021-11-05 22:00:26 -07:00
7c77ee7688 Use case insensitive test for devise sessions 2021-11-05 21:47:02 -07:00
726fab89aa Fix failing tests 2021-11-05 21:26:14 -07:00
a2e20659ac Install capybara-screenshot gem 2021-11-05 21:02:11 -07:00
37fa81aa0a Table must be created before game for test setup 2021-11-04 22:56:09 -07:00
16c4ca936d Fix test navigation 2021-11-03 06:41:15 -07:00
d305d256d1 Dirty fix race condition 2021-11-03 01:07:09 -07:00
65b7c90722 Fix test game path 2021-11-02 20:27:29 -07:00
dc58e28520 Fix card labels 2021-11-02 19:47:51 -07:00
b920410af6 Install ci_reporter gem for Jenkins 2021-10-17 22:03:46 -07:00
3d3bd2d70e Fix tests 2021-09-19 00:26:45 -07:00
fad9c4534a Visit table path instead of game path 2021-09-19 00:24:45 -07:00
b2d13e5856 Move card data to checkbox 2021-09-19 00:21:28 -07:00
05cdf854b7 Config dev email 2021-09-19 00:20:52 -07:00
e8bd50aacb Test helper find card by data 2021-09-19 00:19:53 -07:00
caab453d64 Fix game helper setup include a table 2021-09-19 00:15:09 -07:00
172b682389 Improve selected card UI 2021-09-19 00:13:58 -07:00
e8417c23f7 Capybara test requires visible checkbox 2021-09-18 23:44:02 -07:00
d9fc82d62b Mark test as pending 2021-07-24 04:53:54 -07:00
61cbb753aa Fix syntax errors 2021-07-24 02:15:33 -07:00
398a811810 Fix game tests 2021-07-16 23:24:42 -07:00
6b720d83c9 Mark test as pending 2021-07-16 21:27:42 -07:00
5e63580be8 Fix player count game validation 2021-07-08 23:47:37 -07:00
4ebe60d104 Bugfix spec test 2021-07-08 02:49:57 -07:00
8b5ebc7f7e Bugfix spec test 2021-07-08 01:33:16 -07:00
a13dafc3c5 Update specs 2021-07-07 23:14:13 -07:00
1d7a46f764 Add webdrivers and update gems 2021-07-07 23:13:33 -07:00
0e825aca15 Update syntax of config 2021-07-07 23:02:39 -07:00
4503d117d6 Add card data attribute to inventory cards 2021-07-07 23:01:09 -07:00
aef7f19d6d Fix link route name 2021-07-07 23:00:21 -07:00
b6faf01c06 Fix nil argument bug 2021-07-07 22:42:43 -07:00
23d8b5a1e9 Move to new domain 2021-02-05 05:47:35 -08:00
51cb6b4d56 Use sub folder in production 2020-08-17 00:33:15 -07:00
c49316e348 Use sub folder in production 2020-08-17 00:10:16 -07:00
f5f4845ac2 Update git repo url 2020-08-17 00:05:45 -07:00
3c2b1f4990 Update env to system wide rbenv 2020-08-17 00:04:37 -07:00
99ac2d4f13 Use sub folder in production 2020-08-16 23:58:22 -07:00
e0766fb680 Update gems 2019-11-10 01:52:13 -08:00
59bae293d6 Use image asset tag for cards 2019-11-06 15:10:16 -08:00
cc2ccaed31 Serve static in production 2019-11-06 14:49:39 -08:00
4ba180197f Add tutorial link to home screen 2019-11-06 04:53:17 -08:00
e4f3e46ac6 Redirect to ssl https 2019-11-05 23:44:09 -08:00
7d94762f75 Update devise deprecated code 2019-11-05 23:30:25 -08:00
1f6fb1bad4 Remove upmin-admin gem 2019-11-05 23:03:36 -08:00
99b16f05e2 Use player display_name 2019-11-04 05:06:38 -08:00
a275ed100c Autoload game updates if not taking turn 2019-11-04 05:06:03 -08:00
c14e35bb50 Fix New Game button 2019-11-04 03:54:06 -08:00
7fb829a318 before filter debug 2019-10-29 07:24:43 -07:00
674585bfdc before filter debug 2019-10-29 07:23:37 -07:00
2c4913054f Config deploy for production 2019-10-29 07:14:22 -07:00
43e2ef9ed3 Config deploy for production 2019-10-29 07:07:38 -07:00
7efb52f7c1 Config deploy for production 2019-10-29 07:04:50 -07:00
4beb237a48 Config deploy for production 2019-10-29 07:03:04 -07:00
ce988f54af Config deploy for production 2019-10-29 06:59:02 -07:00
ebf42aa26a Config deploy for production 2019-10-29 06:47:52 -07:00
7c1390ed3c Config deploy for production 2019-10-29 06:43:22 -07:00
f847ca02b9 Updat bin stub 2019-10-29 06:39:36 -07:00
5ca1b68f90 Config deploy for production 2019-10-29 06:32:21 -07:00
f39687b54e Update migrations 2019-10-29 06:12:08 -07:00
1fb3cc5a5c Config deploy for production 2019-10-29 05:33:55 -07:00
191182b80c Config deploy for production 2019-10-29 03:18:24 -07:00
327e50b197 Fix player count in table index, adds user_count to table 2019-10-29 03:10:40 -07:00
5453be7d2d Start adding New Game button to table 2019-10-28 07:08:38 -07:00
12ae163ecd Disable rspec 2019-10-28 05:08:51 -07:00
9416387fe7 Add double run bombs. Logic still incomplete. 2019-10-27 01:34:52 -07:00
19c64bcd84 Add card backs for other players inventory 2019-10-27 00:43:47 -07:00
c64407d0f8 Improve card style 2019-10-27 00:42:52 -07:00
f65a7db32a Add style fir middle player inventory 2019-10-27 00:00:13 -07:00
c6ad426ea2 Fix turn order 2019-10-26 06:17:55 -07:00
6b1179a833 Fix active player id list 2019-10-26 05:40:59 -07:00
d736810cfe Add winner message 2019-10-26 05:31:12 -07:00
f00a111e5e Imorove turn logic regress new end of game bugs 2019-10-26 05:21:20 -07:00
5e3cd7b8ce Improve style 2019-10-26 05:20:15 -07:00
175bb04d31 Disable spring 2019-10-26 04:31:02 -07:00
2702983318 Clear Play To Beat when play is passed by all other players 2019-10-26 04:28:19 -07:00
3c12ce661b Improve style of play to beat 2019-10-26 04:24:34 -07:00
25499b8355 Fix logic for next players turn 2019-10-26 02:18:39 -07:00
c291ed4b66 Improve style of user selected cards 2019-10-26 01:54:09 -07:00
43be6e687a Improve style of player taking turn 2019-10-26 01:52:52 -07:00
9927ca5934 Add visual for player taking turn 2019-10-26 01:37:54 -07:00
ee981552b6 Add play to beat image ui 2019-10-26 01:36:58 -07:00
02cb5e9a65 Add user count validation to start game 2019-10-26 00:41:32 -07:00
f89a62a324 Update gems 2019-10-25 23:29:04 -07:00
51e0f1ad62 Lock sprockets version to avoid config change 2019-10-25 23:28:30 -07:00
62a233d160 Add win count column to user 2019-10-24 19:52:03 -07:00
b5174c1c7f Add confirm alert to pass or stand from seat 2019-10-24 19:51:28 -07:00
bf8549e9a7 Add seats 3 and 4 to tablé 2019-10-24 19:45:33 -07:00
a78538a77b Fix sit stanđ seat player logic 2019-10-24 19:43:57 -07:00
8bcb4c759a Fix bug for player display_name without user 2019-10-24 19:40:04 -07:00
82b26de7aa Add removal of soft_user token 2019-10-24 19:38:28 -07:00
452115a21b Remove unused code 2019-10-24 17:15:59 -07:00
860cc648c6 Fix missing record error with find_by 2019-10-24 17:15:04 -07:00
de11d5e87a Find first empty seat 2019-10-24 17:03:53 -07:00
cda8fc178f Improve player hand style 2019-10-24 17:02:41 -07:00
88a8dbe6a8 Add jquery reloading of table. Fix Play Now 2019-10-21 05:52:44 -07:00
97568ad303 Toying with Play Now 2019-10-20 21:59:40 -07:00
ecda1b8705 Auto refresh unless my turn 2019-10-20 21:57:26 -07:00
bcf28940c4 Toying with stand from active game 2019-10-20 21:56:06 -07:00
72726117cd Add play hand and pass function. 2 player game capable 2019-10-20 18:20:39 -07:00
918fd8f81e Add style for player hand 2019-10-20 17:26:52 -07:00
47cd880041 Adds top seat, player, controls 2019-10-20 16:55:12 -07:00
aab6008279 Adds top seat, player, controls 2019-10-20 05:06:22 -07:00
7183d91d7c Rewrite without react. Can sit stand at a table 2019-10-19 00:38:46 -07:00
7ff24c0266 New dev url 2019-10-19 00:37:07 -07:00
b37d8bec33 Hide tutorial button 2019-10-18 21:12:03 -07:00
fa061de65d Update capybara 2019-10-02 00:24:01 -07:00
441 changed files with 26570 additions and 748 deletions

2
.gitignore vendored
View File

@ -78,7 +78,9 @@ pickle-email-*.html
# vim artifacts
**.swp
*.un~
# Environment files that may contain sensitive data
.env
.powenv
node_modules/

View File

@ -1 +1 @@
2.6.0
3.4.3

View File

@ -7,14 +7,16 @@ require 'capistrano/deploy'
require 'capistrano/rbenv'
require 'capistrano/puma'
install_plugin Capistrano::Puma # Default puma tasks
require 'capistrano/puma/workers'
require 'capistrano/puma/jungle'
install_plugin Capistrano::Puma::Systemd
# require 'capistrano/puma/workers'
# require 'capistrano/puma/jungle'
require 'capistrano/bundler'
# require 'capistrano/nginx'
require 'capistrano/nginx'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/postgresql'
#require 'capistrano/bower'
# TODO enable job scheduler require 'capistrano/delayed_job'
# Includes tasks from other gems included in your Gemfile

39
Gemfile
View File

@ -1,13 +1,15 @@
source 'https://rubygems.org'
ruby '2.6.0'
gem 'rails', '5.2.2'
# TODO Upgrade sprockets
gem 'sprockets', '~> 3.7'
ruby '3.4.3'
gem 'rails', '~> 8.0'
gem 'redis' #, '~> 4.0'
# gem 'bootsnap'
gem 'sprockets' #, '~> 3.7'
gem 'sass-rails' #, '~> 4.0.3'
gem 'uglifier' #, '>= 1.3.0'
# gem 'uglifier' #, '>= 1.3.0'
gem 'coffee-rails' #, '~> 4.0.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jquery-ui-rails'
# gem 'turbolinks'
gem 'jbuilder' #, '~> 2.0'
gem 'sdoc', group: :doc #, '~> 0.4.0'
gem 'devise'
@ -15,7 +17,7 @@ gem 'devise_invitable'
gem 'haml-rails'
gem 'high_voltage'
gem 'pg'
gem 'puma'
gem 'puma' #, '6'
gem 'pundit'
gem 'simple_form'
gem 'dotenv-rails'
@ -31,11 +33,18 @@ group :development do
gem 'capistrano-bundler'
gem 'capistrano-rails'
gem 'capistrano-rails-console'
gem 'capistrano3-puma', '~> 3'
gem 'capistrano3-puma', '~> 6.0.beta'
gem 'capistrano-rbenv'
gem 'capistrano-nginx', github: 'koenpunt/capistrano-nginx'
gem "capistrano-db-tasks", require: false
gem "capistrano-postgresql" #, '~> 4.2.0'
# TODO enable job scheduler gem 'capistrano3-delayed-job', '~> 1.0'
# required for ecdsa key
gem "bcrypt_pbkdf", require: false
gem "net-ssh", ">= 4.0.0", require: false
gem "rbnacl", "~> 3.4", require: false
gem "rbnacl-libsodium", require: false
gem "ed25519", require: false
gem 'guard-bundler'
gem 'guard-rails'
gem 'guard-rspec'
@ -52,7 +61,8 @@ group :development do
gem 'guard-ctags-bundler'
end
group :development, :test do
gem 'factory_girl_rails'
# todo upgrade to factory_bot
# gem 'factory_girl_rails'
gem 'faker'
gem 'pry-rails'
gem 'pry-rescue'
@ -69,3 +79,14 @@ group :test, :staging do
gem 'simplecov', :require => false
end
gem 'capybara-screenshot', :group => :test
gem 'friendly_id', '~> 5.4.0'
gem 'inline_svg'
gem 'importmap-rails'
gem 'turbo-rails'
gem 'stimulus-rails'
gem 'will_paginate'
# TODO enable telegram bots with job scheduler gem 'telegram-bot-ruby', '~> 1.0'
# TODO enable job scheduler gem 'delayed_job_active_record'
# TODO enable job scheduler gem 'daemons'
# TODO enable job scheduler gem "activejob-status", "~> 1.0"

View File

@ -1,5 +1,5 @@
GIT
remote: git://github.com/koenpunt/capistrano-nginx.git
remote: https://github.com/koenpunt/capistrano-nginx.git
revision: 5a91aed41c16fb38b6d9d9462ba1ddfe76dede55
specs:
capistrano-nginx (0.2.1)
@ -8,78 +8,111 @@ GIT
GEM
remote: https://rubygems.org/
specs:
actioncable (5.2.2)
actionpack (= 5.2.2)
actioncable (8.0.2)
actionpack (= 8.0.2)
activesupport (= 8.0.2)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailer (5.2.2)
actionpack (= 5.2.2)
actionview (= 5.2.2)
activejob (= 5.2.2)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (5.2.2)
actionview (= 5.2.2)
activesupport (= 5.2.2)
rack (~> 2.0)
zeitwerk (~> 2.6)
actionmailbox (8.0.2)
actionpack (= 8.0.2)
activejob (= 8.0.2)
activerecord (= 8.0.2)
activestorage (= 8.0.2)
activesupport (= 8.0.2)
mail (>= 2.8.0)
actionmailer (8.0.2)
actionpack (= 8.0.2)
actionview (= 8.0.2)
activejob (= 8.0.2)
activesupport (= 8.0.2)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
actionpack (8.0.2)
actionview (= 8.0.2)
activesupport (= 8.0.2)
nokogiri (>= 1.8.5)
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.2.2)
activesupport (= 5.2.2)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
useragent (~> 0.16)
actiontext (8.0.2)
actionpack (= 8.0.2)
activerecord (= 8.0.2)
activestorage (= 8.0.2)
activesupport (= 8.0.2)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (8.0.2)
activesupport (= 8.0.2)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (5.2.2)
activesupport (= 5.2.2)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
activejob (8.0.2)
activesupport (= 8.0.2)
globalid (>= 0.3.6)
activemodel (5.2.2)
activesupport (= 5.2.2)
activerecord (5.2.2)
activemodel (= 5.2.2)
activesupport (= 5.2.2)
arel (>= 9.0)
activestorage (5.2.2)
actionpack (= 5.2.2)
activerecord (= 5.2.2)
marcel (~> 0.3.1)
activesupport (5.2.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
airbrussh (1.4.0)
activemodel (8.0.2)
activesupport (= 8.0.2)
activerecord (8.0.2)
activemodel (= 8.0.2)
activesupport (= 8.0.2)
timeout (>= 0.4.0)
activestorage (8.0.2)
actionpack (= 8.0.2)
activejob (= 8.0.2)
activerecord (= 8.0.2)
activesupport (= 8.0.2)
marcel (~> 1.0)
activesupport (8.0.2)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
airbrussh (1.5.3)
sshkit (>= 1.6.1, != 1.7.0)
arel (9.0.0)
ast (2.4.2)
ast (2.4.3)
babel-source (5.8.35)
babel-transpiler (0.7.0)
babel-source (>= 4.0, < 6)
execjs (~> 2.0)
bcrypt (3.1.16)
better_errors (2.9.1)
coderay (>= 1.0.0)
base64 (0.2.0)
bcrypt (3.1.20)
bcrypt_pbkdf (1.1.1)
benchmark (0.4.0)
better_errors (2.10.1)
erubi (>= 1.0.0)
rack (>= 0.9.0)
binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
builder (3.2.4)
capistrano (3.16.0)
rouge (>= 1.0.0)
bigdecimal (3.1.9)
binding_of_caller (1.0.1)
debug_inspector (>= 1.2.0)
builder (3.3.0)
capistrano (3.19.2)
airbrussh (>= 1.0.0)
i18n
rake (>= 10.0.0)
sshkit (>= 1.9.0)
capistrano-bundler (2.0.1)
capistrano-bundler (2.1.1)
capistrano (~> 3.1)
capistrano-db-tasks (0.6)
capistrano (>= 3.0.0)
capistrano-postgresql (6.2.0)
capistrano (>= 3.0)
sshkit (>= 1.17.0)
capistrano-rails (1.6.1)
capistrano-rails (1.7.0)
capistrano (~> 3.1)
capistrano-bundler (>= 1.1, < 3)
capistrano-rails-console (2.3.0)
@ -88,25 +121,27 @@ GEM
capistrano-rbenv (2.2.0)
capistrano (~> 3.1)
sshkit (~> 1.3)
capistrano3-puma (3.1.1)
capistrano3-puma (6.0.0)
capistrano (~> 3.7)
capistrano-bundler
puma (~> 3.4)
capybara (3.36.0)
puma (>= 5.1, < 7.0)
capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
capybara-screenshot (1.0.25)
capybara-screenshot (1.0.26)
capybara (>= 1.0, < 4)
launchy
childprocess (4.1.0)
ci_reporter (2.0.0)
childprocess (5.1.0)
logger (~> 1.5)
ci_reporter (2.1.0)
builder (>= 2.1.2)
rexml
ci_reporter_rspec (1.0.0)
ci_reporter (~> 2.0)
rspec (>= 2.14, < 4)
@ -118,60 +153,63 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.12.2)
concurrent-ruby (1.1.9)
connection_pool (2.2.5)
concurrent-ruby (1.3.5)
connection_pool (2.5.1)
crass (1.0.6)
database_cleaner (2.0.1)
database_cleaner-active_record (~> 2.0.0)
database_cleaner-active_record (2.0.1)
database_cleaner (2.1.0)
database_cleaner-active_record (>= 2, < 3)
database_cleaner-active_record (2.2.0)
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
debug_inspector (1.1.0)
devise (4.8.0)
date (3.4.1)
debug_inspector (1.2.0)
devise (4.9.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
devise_invitable (2.0.5)
devise_invitable (2.0.10)
actionmailer (>= 5.0)
devise (>= 4.6)
diff-lcs (1.4.4)
docile (1.4.0)
dotenv (2.7.6)
dotenv-rails (2.7.6)
dotenv (= 2.7.6)
railties (>= 3.2)
diff-lcs (1.6.1)
docile (1.4.1)
dotenv (3.1.8)
dotenv-rails (3.1.8)
dotenv (= 3.1.8)
railties (>= 6.1)
drb (2.2.1)
ed25519 (1.3.0)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
erubi (1.10.0)
erubi (1.13.1)
erubis (2.7.0)
eventmachine (1.2.7)
execjs (2.8.1)
factory_girl (4.9.0)
activesupport (>= 3.0.0)
factory_girl_rails (4.9.0)
factory_girl (~> 4.9.0)
railties (>= 3.0.0)
faker (2.19.0)
i18n (>= 1.6, < 2)
ffi (1.15.4)
formatador (0.3.0)
globalid (0.5.2)
activesupport (>= 5.0)
guard (2.18.0)
execjs (2.10.0)
faker (3.5.1)
i18n (>= 1.8.11, < 2)
ffi (1.17.2)
ffi (1.17.2-x86_64-linux-gnu)
formatador (1.1.0)
friendly_id (5.4.2)
activerecord (>= 4.0.0)
globalid (1.2.1)
activesupport (>= 6.1)
guard (2.19.1)
formatador (>= 0.2.4)
listen (>= 2.7, < 4.0)
logger (~> 1.6)
lumberjack (>= 1.0.12, < 2.0)
nenv (~> 0.1)
notiffany (~> 0.0)
ostruct (~> 0.6)
pry (>= 0.13.0)
shellany (~> 0.0)
thor (>= 0.18.1)
guard-bundler (2.2.1)
bundler (>= 1.3.0, < 3)
guard-bundler (3.0.1)
bundler (>= 2.1, < 3)
guard (~> 2.2)
guard-compat (~> 1.1)
guard-compat (1.2.1)
@ -190,170 +228,239 @@ GEM
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
haml (5.2.2)
temple (>= 0.8.0)
haml (6.3.0)
temple (>= 0.8.2)
thor
tilt
haml-rails (2.0.1)
haml-rails (2.1.0)
actionpack (>= 5.1)
activesupport (>= 5.1)
haml (>= 4.0.6, < 6.0)
html2haml (>= 1.0.1)
haml (>= 4.0.6)
railties (>= 5.1)
high_voltage (3.1.2)
html2haml (2.2.0)
high_voltage (4.0.0)
html2haml (2.3.0)
erubis (~> 2.7.0)
haml (>= 4.0, < 6)
haml (>= 4.0)
nokogiri (>= 1.6.0)
ruby_parser (~> 3.5)
http_parser.rb (0.8.0)
hub (1.12.4)
i18n (1.8.11)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
importmap-rails (2.1.0)
actionpack (>= 6.0.0)
activesupport (>= 6.0.0)
railties (>= 6.0.0)
inline_svg (1.10.0)
activesupport (>= 3.0)
nokogiri (>= 1.6)
interception (0.5)
jbuilder (2.11.2)
io-console (0.8.0)
irb (1.15.2)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jbuilder (2.13.0)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jquery-rails (4.4.0)
jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
launchy (2.5.0)
addressable (~> 2.7)
listen (3.7.0)
jquery-ui-rails (7.0.0)
railties (>= 3.2.16)
json (2.10.2)
language_server-protocol (3.17.0.4)
launchy (3.1.1)
addressable (~> 2.8)
childprocess (~> 5.0)
logger (~> 1.6)
lint_roller (1.1.0)
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.12.0)
logger (1.7.0)
loofah (2.24.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
lumberjack (1.2.8)
mail (2.7.1)
nokogiri (>= 1.12.0)
lumberjack (1.2.10)
mail (2.8.1)
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
net-imap
net-pop
net-smtp
marcel (1.0.4)
matrix (0.4.2)
method_source (1.0.0)
mimemagic (0.3.10)
nokogiri (~> 1)
rake
mini_mime (1.1.2)
mini_portile2 (2.6.1)
minitest (5.14.4)
method_source (1.1.0)
mini_mime (1.1.5)
mini_portile2 (2.8.8)
minitest (5.25.5)
multi_json (1.15.0)
nenv (0.3.0)
net-scp (3.0.0)
net-ssh (>= 2.6.5, < 7.0.0)
net-ssh (6.1.0)
nio4r (2.5.8)
nokogiri (1.12.5)
mini_portile2 (~> 2.6.1)
net-imap (0.5.7)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
net-scp (4.1.0)
net-ssh (>= 2.6.5, < 8.0.0)
net-sftp (4.0.0)
net-ssh (>= 5.0.0, < 8.0.0)
net-smtp (0.5.1)
net-protocol
net-ssh (7.3.0)
nio4r (2.7.4)
nokogiri (1.18.8)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nokogiri (1.18.8-x86_64-linux-gnu)
racc (~> 1.4)
notiffany (0.1.3)
nenv (~> 0.1)
shellany (~> 0.0)
orm_adapter (0.5.0)
parallel (1.21.0)
parallel_tests (3.7.3)
ostruct (0.6.1)
parallel (1.27.0)
parallel_tests (5.1.0)
parallel
parser (3.0.2.0)
parser (3.3.8.0)
ast (~> 2.4.1)
pg (1.2.3)
pry (0.14.1)
racc
pg (1.5.9)
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
prism (1.4.0)
pry (0.15.2)
coderay (~> 1.1)
method_source (~> 1.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
pry-rescue (1.5.2)
pry-rails (0.3.11)
pry (>= 0.13.0)
pry-rescue (1.6.0)
interception (>= 0.5)
pry (>= 0.12.0)
public_suffix (4.0.6)
puma (3.12.6)
pundit (2.1.1)
psych (5.2.3)
date
stringio
public_suffix (6.0.1)
puma (6.6.0)
nio4r (~> 2.0)
pundit (2.5.0)
activesupport (>= 3.0.0)
racc (1.6.0)
rack (2.2.3)
rack-livereload (0.3.17)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (5.2.2)
actioncable (= 5.2.2)
actionmailer (= 5.2.2)
actionpack (= 5.2.2)
actionview (= 5.2.2)
activejob (= 5.2.2)
activemodel (= 5.2.2)
activerecord (= 5.2.2)
activestorage (= 5.2.2)
activesupport (= 5.2.2)
bundler (>= 1.3.0)
railties (= 5.2.2)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
racc (1.8.1)
rack (3.1.13)
rack-livereload (0.6.1)
rack (>= 3.0, < 3.2)
rack-session (2.1.0)
base64 (>= 0.1.0)
rack (>= 3.0.0)
rack-test (2.2.0)
rack (>= 1.3)
rackup (2.2.1)
rack (>= 3)
rails (8.0.2)
actioncable (= 8.0.2)
actionmailbox (= 8.0.2)
actionmailer (= 8.0.2)
actionpack (= 8.0.2)
actiontext (= 8.0.2)
actionview (= 8.0.2)
activejob (= 8.0.2)
activemodel (= 8.0.2)
activerecord (= 8.0.2)
activestorage (= 8.0.2)
activesupport (= 8.0.2)
bundler (>= 1.15.0)
railties (= 8.0.2)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.4.2)
loofah (~> 2.3)
rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
rails_layout (1.0.42)
railties (5.2.2)
actionpack (= 5.2.2)
activesupport (= 5.2.2)
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
rainbow (3.0.0)
rake (13.0.6)
railties (8.0.2)
actionpack (= 8.0.2)
activesupport (= 8.0.2)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.2.1)
rb-fchange (0.0.6)
ffi
rb-fsevent (0.11.0)
rb-inotify (0.10.1)
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
ffi (~> 1.0)
rdoc (6.3.3)
react-rails (2.6.1)
rbnacl (3.4.0)
ffi
rbnacl-libsodium (1.0.16)
rbnacl (>= 3.0.1)
rdoc (6.13.1)
psych (>= 4.0.0)
react-rails (3.2.1)
babel-transpiler (>= 0.7.0)
connection_pool
execjs
railties (>= 3.2)
tilt
regexp_parser (2.1.1)
responders (3.0.1)
actionpack (>= 5.0)
railties (>= 5.0)
rexml (3.2.5)
rspec (3.10.0)
rspec-core (~> 3.10.0)
rspec-expectations (~> 3.10.0)
rspec-mocks (~> 3.10.0)
rspec-core (3.10.1)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-mocks (3.10.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-rails (5.0.2)
redis (5.4.0)
redis-client (>= 0.22.0)
redis-client (0.24.0)
connection_pool
regexp_parser (2.10.0)
reline (0.6.1)
io-console (~> 0.5)
responders (3.1.1)
actionpack (>= 5.2)
activesupport (>= 5.2)
railties (>= 5.2)
rspec-core (~> 3.10)
rspec-expectations (~> 3.10)
rspec-mocks (~> 3.10)
rspec-support (~> 3.10)
rspec-support (3.10.3)
rubocop (1.22.3)
rexml (3.4.1)
rouge (4.5.1)
rspec (3.13.0)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.3)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (7.1.1)
actionpack (>= 7.0)
activesupport (>= 7.0)
railties (>= 7.0)
rspec-core (~> 3.13)
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
rspec-support (~> 3.13)
rspec-support (3.13.2)
rubocop (1.75.3)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (~> 1.10)
parser (>= 3.0.0.0)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
rubocop-ast (>= 1.12.0, < 2.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.44.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.13.0)
parser (>= 3.0.1.1)
ruby-progressbar (1.11.0)
ruby_parser (3.18.1)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.44.1)
parser (>= 3.3.7.2)
prism (~> 1.4)
ruby-progressbar (1.13.0)
ruby_parser (3.21.1)
racc (~> 1.5)
sexp_processor (~> 4.16)
rubyzip (2.3.2)
rubyzip (2.4.1)
sass-rails (6.0.0)
sassc-rails (~> 2.1, >= 2.1.1)
sassc (2.4.0)
@ -364,66 +471,83 @@ GEM
sprockets (> 3.0)
sprockets-rails
tilt
sdoc (2.2.0)
sdoc (2.6.1)
rdoc (>= 5.0)
selenium-webdriver (4.0.3)
childprocess (>= 0.5, < 5.0)
securerandom (0.4.1)
selenium-webdriver (4.10.0)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2)
sexp_processor (4.16.0)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
sexp_processor (4.17.3)
shellany (0.0.1)
simple_form (5.1.0)
simple_form (5.3.1)
actionpack (>= 5.2)
activemodel (>= 5.2)
simplecov (0.21.2)
simplecov (0.22.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov_json_formatter (0.1.3)
spring (3.0.0)
simplecov-html (0.13.1)
simplecov_json_formatter (0.1.4)
spring (4.3.0)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
sprockets (3.7.2)
sprockets (4.2.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.3.0)
actionpack (>= 5.2)
activesupport (>= 5.2)
logger
rack (>= 2.2.4, < 4)
sprockets-rails (3.5.2)
actionpack (>= 6.1)
activesupport (>= 6.1)
sprockets (>= 3.0.0)
sshkit (1.21.2)
sshkit (1.24.0)
base64
logger
net-scp (>= 1.1.2)
net-sftp (>= 2.1.2)
net-ssh (>= 2.8.0)
ostruct
sshkit-interactive (0.3.0)
sshkit (~> 1.12)
temple (0.8.2)
thor (1.1.0)
thread_safe (0.3.6)
tilt (2.0.10)
turbolinks (5.2.1)
turbolinks-source (~> 5.2)
turbolinks-source (5.2.0)
tzinfo (1.2.9)
thread_safe (~> 0.1)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (2.1.0)
stimulus-rails (1.3.4)
railties (>= 6.0.0)
stringio (3.1.7)
temple (0.10.3)
thor (1.3.2)
tilt (2.6.0)
timeout (0.4.3)
turbo-rails (2.0.13)
actionpack (>= 7.1.0)
railties (>= 7.1.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (3.1.4)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
uri (1.0.3)
useragent (0.16.11)
warden (1.2.9)
rack (>= 2.0.9)
webdrivers (5.0.0)
webdrivers (5.3.1)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (~> 4.0)
websocket-driver (0.7.5)
selenium-webdriver (~> 4.0, < 4.11)
websocket (1.2.11)
websocket-driver (0.7.7)
base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
will_paginate (4.0.1)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.7.2)
PLATFORMS
ruby
x86_64-linux
DEPENDENCIES
bcrypt_pbkdf
better_errors
binding_of_caller
capistrano
@ -434,7 +558,7 @@ DEPENDENCIES
capistrano-rails
capistrano-rails-console
capistrano-rbenv
capistrano3-puma (~> 3)
capistrano3-puma (~> 6.0.beta)
capybara
capybara-screenshot
ci_reporter_rspec
@ -443,8 +567,9 @@ DEPENDENCIES
devise
devise_invitable
dotenv-rails
factory_girl_rails
ed25519
faker
friendly_id (~> 5.4.0)
guard-bundler
guard-ctags-bundler
guard-livereload
@ -454,9 +579,13 @@ DEPENDENCIES
high_voltage
html2haml
hub
importmap-rails
inline_svg
jbuilder
jquery-rails
jquery-ui-rails
launchy
net-ssh (>= 4.0.0)
parallel_tests
pg
pry-rails
@ -464,12 +593,15 @@ DEPENDENCIES
puma
pundit
rack-livereload
rails (= 5.2.2)
rails (~> 8.0)
rails_layout
rb-fchange
rb-fsevent
rb-inotify
rbnacl (~> 3.4)
rbnacl-libsodium
react-rails
redis
rspec-rails
rubocop
sass-rails
@ -479,13 +611,14 @@ DEPENDENCIES
simplecov
spring
spring-commands-rspec
sprockets (~> 3.7)
turbolinks
uglifier
sprockets
stimulus-rails
turbo-rails
webdrivers
will_paginate
RUBY VERSION
ruby 2.6.0p0
ruby 3.4.3p32
BUNDLED WITH
1.17.3
2.4.22

View File

@ -35,7 +35,7 @@ guard :bundler do
files.each { |file| watch(helper.real_path(file)) }
end
guard 'rails', host: '0.0.0.0', port: 9913 do
guard 'rails', host: '0.0.0.0', port: 9914 do
watch('Gemfile.lock')
watch(%r{^(config|lib)/.*})
end
@ -108,3 +108,42 @@ end
# watch(/^(app|lib|spec\/support)\/.*\.rb$/)
# watch('Gemfile.lock')
#end
guard 'livereload' do
extensions = {
css: :css,
scss: :css,
sass: :css,
js: :js,
coffee: :js,
html: :html,
png: :png,
gif: :gif,
jpg: :jpg,
jpeg: :jpeg,
# less: :less, # uncomment if you want LESS stylesheets done in browser
}
rails_view_exts = %w(erb haml slim)
# file types LiveReload may optimize refresh for
compiled_exts = extensions.values.uniq
watch(%r{public/.+\.(#{compiled_exts * '|'})})
extensions.each do |ext, type|
watch(%r{
(?:app|vendor)
(?:/assets/\w+/(?<path>[^.]+) # path+base without extension
(?<ext>\.#{ext})) # matching extension (must be first encountered)
(?:\.\w+|$) # other extensions
}x) do |m|
path = m[1]
"/assets/#{path}.#{type}"
end
end
# file needing a full reload of the page anyway
watch(%r{app/views/.+\.(#{rails_view_exts * '|'})$})
watch(%r{app/helpers/.+\.rb})
watch(%r{config/locales/.+\.yml})
end

View File

@ -1,9 +1,32 @@
Thirteen Tien Len
================
Development Environment Setup
-----------------------------
bundle install
cp config/{database.yml.example,database.yml}
rake db:setup
guard
TODO
----
- Add push notifications https://github.com/rpush/rpush#webpush
- Continue to Private Chat https://www.honeybadger.io/blog/chat-app-rails-actioncable-turbo/
- Implement video chat https://github.com/domchristie/webrtc-hotwire-rails
- Abandon previous video chat solution
- change from google ice server ./frontend/components/video_util.js:6
- Add video chat https://medium.com/@nicolas.e.schneider/videochat-in-under-30-a-rails-react-tutorial-534930c6cd96
- Refactor seat.jsx buttons in to a <form>.
- 1st 2nd 3rd place messages. End game message.

View File

@ -0,0 +1,7 @@
//= link gems.js
//= link jquery.js
//= link libraries/swiped.min.js
//= link_tree ../images
//= link_directory ../stylesheets .css
//= link_tree ../../javascript .js
//= link_tree ../../../vendor/assets/javascripts .js

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

10
app/assets/images/icp-coin.svg Executable file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -0,0 +1,13 @@
// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
//
//= require action_cable
//= require_self
//= require_tree ./channels
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer();
}).call(this);

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -0,0 +1,9 @@
#App.call = App.cable.subscriptions.create "CallChannel",
# connected: ->
# # Called when the subscription is ready for use on the server
#
# disconnected: ->
# # Called when the subscription has been terminated by the server
#
# received: (data) ->
# # Called when there's incoming data on the websocket for this channel

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -0,0 +1,9 @@
import { Application } from '@hotwired/stimulus'
const application = Application.start()
// Configure Stimulus development experience
application.debug = false
window.Stimulus = application
export { application }

View File

@ -0,0 +1,5 @@
import { application } from 'controllers/application'
// Eager load all controllers defined in the import map under controllers/**/*_controller
import { eagerLoadControllersFrom } from '@hotwired/stimulus-loading'
eagerLoadControllersFrom('controllers', application)

View File

@ -0,0 +1,17 @@
import { Controller } from '@hotwired/stimulus'
export default class MediumController extends Controller {
connect () {
this.reRenderMediaElement()
}
// Fix potentially blank videos due to autoplay rules?
reRenderMediaElement () {
const mediaElement = this.mediaElementTarget
const clone = mediaElement.cloneNode(true)
mediaElement.parentNode.insertBefore(clone, mediaElement)
mediaElement.remove()
}
}
MediumController.targets = ['mediaElement']

View File

@ -0,0 +1,147 @@
import { Controller } from '@hotwired/stimulus'
import Client from 'models/client'
import WebrtcNegotiation from 'models/webrtc_negotiation'
import VideoRoomSubscription from 'subscriptions/video_room_subscription'
import Signaller from 'subscriptions/signaling_subscription'
export default class VideoRoomController extends Controller {
connect() {
this.clients = {}
this.client = new Client(this.clientIdValue)
this.subscription = new VideoRoomSubscription({
delegate: this,
id: this.idValue,
clientId: this.client.id
})
this.signaller = new Signaller({
delegate: this,
id: this.idValue,
clientId: this.client.id
})
this.client.on('iceConnection:checking', ({ detail: { otherClient } }) => {
this.startStreamingTo(otherClient)
})
}
async enter () {
try {
const constraints = { audio: true, video: true }
this.client.stream = await navigator.mediaDevices.getUserMedia(constraints)
this.localMediumTarget.srcObject = this.client.stream
this.localMediumTarget.muted = true // Keep muted on Firefox
this.enterTarget.hidden = true
this.subscription.start()
this.signaller.start()
} catch (error) {
console.error(error)
}
}
greetNewClient ({ from }) {
const otherClient = this.findOrCreateClient(from)
otherClient.newcomer = true
this.subscription.greet({ to: otherClient.id, from: this.client.id })
}
remoteMediumTargetConnected (element) {
const clientId = element.id.replace('medium_', '')
this.negotiateConnection(clientId)
}
remoteMediumTargetDisconnected (element) {
const clientId = element.id.replace('medium_', '')
this.teardownClient(clientId)
}
negotiateConnection (clientId) {
const otherClient = this.findOrCreateClient(clientId)
// Be polite to newcomers!
const polite = !!otherClient.newcomer
otherClient.negotiation = this.createNegotiation({ otherClient, polite })
// The polite client sets up the negotiation last, so we can start streaming
// The impolite client signals to the other client that it's ready
if (polite) {
this.startStreamingTo(otherClient)
} else {
this.subscription.greet({ to: otherClient.id, from: this.client.id })
}
}
teardownClient (clientId) {
this.clients[clientId].stop()
delete this.clients[clientId]
}
createNegotiation ({ otherClient, polite }) {
const negotiation = new WebrtcNegotiation({
signaller: this.signaller,
client: this.client,
otherClient: otherClient,
polite
})
otherClient.on('track', ({ detail }) => {
this.startStreamingFrom(otherClient.id, detail)
})
return negotiation
}
startStreamingTo (otherClient) {
this.client.streamTo(otherClient)
}
startStreamingFrom (id, { track, streams: [stream] }) {
const remoteMediaElement = this.findRemoteMediaElement(id)
if (!remoteMediaElement.srcObject) {
remoteMediaElement.srcObject = stream
}
}
findOrCreateClient (id) {
return this.clients[id] || (this.clients[id] = new Client(id))
}
findRemoteMediaElement (clientId) {
const target = this.remoteMediumTargets.find(
target => target.id === `medium_${clientId}`
)
return target ? target.querySelector('video') : null
}
negotiationFor (id) {
return this.clients[id].negotiation
}
// VideoRoomSubscription Delegate
videoRoomPinged (data) {
this.greetNewClient(data)
}
// Signaler Delegate
sdpDescriptionReceived ({ from, description }) {
this.negotiationFor(from).setDescription(description)
}
iceCandidateReceived ({ from, candidate }) {
this.negotiationFor(from).addCandidate(candidate)
}
negotiationRestarted ({ from }) {
const negotiation = this.negotiationFor(from)
negotiation.restart()
negotiation.createOffer()
}
}
VideoRoomController.values = { id: String, clientId: String }
VideoRoomController.targets = ['localMedium', 'remoteMedium', 'enter']

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -0,0 +1,117 @@
(function ($, window, undefined) {
$.fn.marqueeify = function (options) {
var settings = $.extend({
horizontal: true,
vertical: true,
speed: 100, // In pixels per second
color: "#00ffff",
zindex: 0,
container: $(this).parent(),
bumpEdge: function () {}
}, options);
return this.each(function () {
var containerWidth, containerHeight, elWidth, elHeight, move, getSizes,
$el = $(this);
getSizes = function () {
containerWidth = settings.container.outerWidth();
containerHeight = settings.container.outerHeight();
elWidth = $el.outerWidth();
elHeight = $el.outerHeight();
};
move = {
right: function () {
$el.css("z-index", Math.round(settings.zindex));
$el.animate({left: (containerWidth - elWidth)}, {duration: ((containerWidth/settings.speed) * 1000), queue: false, easing: "linear", complete: function () {
settings.bumpEdge();
move.left();
}});
},
left: function () {
$el.css("z-index", Math.round(settings.zindex));
$el.animate({left: 0}, {duration: ((containerWidth/settings.speed) * 1000), queue: false, easing: "linear", complete: function () {
settings.bumpEdge();
move.right();
}});
},
down: function () {
$el.css("z-index", Math.round(settings.zindex));
$el.animate({top: (containerHeight - elHeight)}, {duration: ((containerHeight/settings.speed) * 1000), queue: false, easing: "linear", complete: function () {
settings.bumpEdge();
move.up();
}});
},
up: function () {
$el.css("z-index", Math.round(settings.zindex));
$el.animate({top: 0}, {duration: ((containerHeight/settings.speed) * 1000), queue: false, easing: "linear", complete: function () {
settings.bumpEdge();
move.down();
}});
}
};
getSizes();
if (settings.horizontal) {
move.right();
}
if (settings.vertical) {
move.down();
}
// Make that shit responsive!
$(window).resize( function() {
getSizes();
});
});
};
})(jQuery, window);
$(document).ready( function() {
$(".eyecandy").bind('my-event', function(event) {
alert(event);
});
$("#mySecondDiv").trigger('my-event', [1, 2]);
$('.eyecandy').on( "click", function() {
$(this).toggleClass("clicked");
// $(this).marqueeify({
// speed: Math.random()*420,
// bumpEdge: function () {
// var newColor = "hsl(" + Math.floor(Math.random()*360) + ", 100%, 50%)";
// $('.marquee').css('background', newColor);
// $(this)[0].speed = Math.random()*420;
// }
// });
} );
$('.eyecandy').marqueeify({
speed: 300,
bumpEdge: function () {
// svg bgcolor
// var newColor = "hsl(" + Math.floor(Math.random()*360) + ", 100%, 50%)";
var newColor = Math.floor(Math.random()*16777215).toString(16);
// console.log($(this)[0].self);
// console.log($(this)[0].color);
// console.log($(this)[0].self);
// .css("background-color", "#" + newColor);
//.css("background-color", "#00ffff");
$(this)[0].speed = Math.random()*420;
$(this)[0].zindex = Math.random()*20;
// .parent.css("display", "none");
// console.log(this);
// delete this;
}
});
// $( ".eyecandy" ).draggable({
// addClasses: true
// });
$(".home-headline,#home-headline").draggable({
addClasses: true
});
});

View File

@ -11,12 +11,19 @@
// about supported directives.
//
//= require jquery
//= require jquery-ui
//= require jquery_ujs
//= require turbolinks
// require turbolinks
// require react
// require react_ujs
//= require components
//= require qrcode.min.js
// require components
// require qrcode.min.js
//= require eyecandy
// require cable
// require_tree ./subscriptions
// require_tree ./models
// require_tree ./libraries
// require_tree ./controllers
// require react-rails-hot-loader
// require_tree .
@ -28,3 +35,4 @@ $(document).ready(function(){
$('#play-buttons').load("#{request.path} #play-buttons");
}, 2000);
});

View File

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
!function(){function t(t,e){document.addEventListener(t,function(t){a._elems.forEach(function(i){for(var n=t.target;n;){if(n===i.elem)return i[e](t),!1;n=n.parentNode}return!1})})}function e(){var t=[].shift.call(arguments),e=arguments[0];for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}var i=window.navigator.msPointerEnabled,n={start:i?"MSPointerDown":"touchstart",move:i?"MSPointerMove":"touchmove",end:i?"MSPointerUp":"touchend"},o=function(){var t=window.getComputedStyle(document.documentElement,""),e=(Array.prototype.slice.call(t).join("").match(/-(moz|webkit|ms)-/)||""===t.OLink&&["","o"])[1];return"-"+e+"-"}(),s=function(){var t,e=document.createElement("fakeelement"),i={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(t in i)if(void 0!==e.style[t])return i[t]}(),r={transition:o+"transition",transform:o+"transform"},h=function(){},a=function(t){var i={duration:200,tolerance:50,time:200,dir:1,right:0,left:0};t=e(i,t||{}),this.duration=t.duration,this.tolerance=t.tolerance,this.time=t.time,this.width=t.left||t.right,this.elem=t.elem,this.list=t.list,this.dir=t.dir,this.group=t.group,this.id=a.elemId++,this.onOpen="function"==typeof t.onOpen?t.onOpen:h,this.onClose="function"==typeof t.onClose?t.onClose:h,this.right=t.right,this.left=t.left,(t.right>0&&t.tolerance>t.right||t.left>0&&t.tolerance>t.left)&&console.warn("tolerance must be less then left and right")};a._elems=[],a.groupCounter=0,a.elemId=0,a.init=function(t){a.groupCounter++;var i=document.querySelectorAll(t.query),n=[];return delete t.query,[].forEach.call(i,function(i){var o=e({elem:i,group:a.groupCounter},t);n.push(new a(o))}),a._bindEvents(),a._elems=a._elems.concat(n),1===n.length?n[0]:n},a._closeAll=function(t){a._elems.forEach(function(e){e.group===t&&e.close(!0)})},a.prototype.transitionEnd=function(t,e){function i(){e.call(n),t.removeEventListener(s,i)}var n=this;t.addEventListener(s,i)},a.prototype.touchStart=function(t){var e=t.changedTouches[0];1===t.touches.length&&(this.touchId=e.identifier,this.x=e.pageX,this.y=e.pageY,this.startTime=new Date,this.resetValue(),this.list?a._closeAll(this.group):this.close(!0))},a.prototype.touchMove=function(t){var e=t.changedTouches[0];this.isValidTouch(t)&&(this.delta=e.pageX-this.x,this.dir=this.delta<0?-1:1,this.width=this.delta<0?this.right:this.left,this.defineUserAction(e),this.startSwipe&&(this.move(),t.preventDefault()))},a.prototype.touchEnd=function(t){this.isValidTouch(t,!0)&&this.startSwipe&&(this.dir*this.delta>this.tolerance||new Date-this.startTime<this.time?this.open():this.close(),t.stopPropagation(),t.preventDefault())},a.prototype.open=function(t){this.animation(this.dir*this.width),this.swiped=!0,t||this.transitionEnd(this.elem,this.onOpen),this.resetValue()},a.prototype.close=function(t){this.animation(0),this.swiped=!1,t||this.transitionEnd(this.elem,this.onClose),this.resetValue()},a.prototype.toggle=function(){this.swiped?this.close():this.open()},a.prototype.resetValue=function(){this.startSwipe=!1,this.startScroll=!1,this.delta=0},a._bindEvents=function(){return a.eventBinded?!1:(t(n.move,"touchMove"),t(n.end,"touchEnd"),t(n.start,"touchStart"),void(a.eventBinded=!0))},a.prototype.defineUserAction=function(t){var e=10,i=10;Math.abs(this.y-t.pageY)>i&&!this.startSwipe?this.startScroll=!0:Math.abs(this.delta)>e&&!this.startScroll&&(this.startSwipe=!0)},a.prototype.isValidTouch=function(t,e){var i=e?"changedTouches":"targetTouches";return t[i][0].identifier===this.touchId},a.prototype.move=function(){if(this.dir>0&&(this.delta<0||0===this.left)||this.dir<0&&(this.delta>0||0===this.right))return!1;var t=Math.abs(this.delta);t>this.width&&(this.delta=this.dir*(this.width+(t-this.width)/8)),this.animation(this.delta,0)},a.prototype.animation=function(t,e){e=void 0===e?this.duration:e,this.elem.style.cssText=r.transition+":"+r.transform+" "+e+"ms; "+r.transform+":translate3d("+t+"px, 0px, 0px)"},a.prototype.destroy=function(t){var e=this.id;a._elems.forEach(function(t,i){t.id===e&&a._elems.splice(i,1)}),t&&this.elem.parentNode.removeChild(this.elem)},window.Swiped=a}();

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -0,0 +1,43 @@
export default class Client {
constructor (id) {
this.callbacks = {}
this.id = id
}
get peerConnection () {
return this.negotiation && this.negotiation.peerConnection
}
streamTo (otherClient) {
if (!otherClient.streaming) {
this.stream.getTracks().forEach(track => {
otherClient.peerConnection.addTrack(track, this.stream)
})
otherClient.streaming = true
}
}
on (name, callback) {
const names = name.split(' ')
names.forEach((name) => {
this.callbacks[name] = this.callbacks[name] || []
this.callbacks[name].push(callback)
})
}
broadcast (name, data) {
(this.callbacks[name] || []).forEach(
callback => callback.call(null, { type: name, detail: data })
)
}
off (name) {
if (name) return delete this.callbacks[name]
else this.callbacks = {}
}
stop () {
this.off()
this.negotiation.stop()
}
}

View File

@ -0,0 +1,183 @@
const RETRY_LIMIT = 10
const peerConnectionConfig = {
iceServers: [
{
urls: [
'stun:stun.l.google.com:19302',
'stun:global.stun.twilio.com:3478'
]
}
],
sdpSemantics: 'unified-plan'
}
export default class WebrtcNegotiation {
constructor ({ client, otherClient, polite, signaller }) {
this.client = client
this.otherClient = otherClient
this.polite = polite
this.signaller = signaller
this.makingOffer = false
this.isSettingRemoteAnswerPending = false
this.candidates = []
this.retryCount = 0
this.start()
}
async createOffer () {
if (!this.readyToMakeOffer) return
try {
this.makingOffer = true
await this.setLocalDescription(await this.peerConnection.createOffer())
} catch (error) {
console.error(error)
} finally {
this.makingOffer = false
}
}
async setDescription (description) {
try {
if (this.ignore(description)) return
await this.setRemoteDescription(description)
if (description.type === 'offer') {
await this.setLocalDescription(await this.peerConnection.createAnswer())
}
} catch (error) {
if (this.retryCount < RETRY_LIMIT) {
this.initiateManualRollback()
this.retryCount++
} else {
this.stop()
console.error(`Negotiation failed after ${this.retryCount} retries`)
}
}
}
async setLocalDescription (description) {
await this.peerConnection.setLocalDescription(description)
this.signaller.signal({
type: this.peerConnection.localDescription ? 'description' : undefined,
to: this.otherClient.id,
from: this.client.id,
description: this.peerConnection.localDescription
})
}
async setRemoteDescription (description) {
this.isSettingRemoteAnswerPending = description.type === 'answer'
await this.peerConnection.setRemoteDescription(description) // SRD rolls back as needed
this.addCandidates()
this.isSettingRemoteAnswerPending = false
}
addCandidate (candidate) {
this.candidates.push(candidate)
this.addCandidates()
}
// TODO try/catch and ignore failures if necessary?
addCandidates () {
if (this.peerConnection.remoteDescription) {
while (this.candidates.length) {
this.peerConnection.addIceCandidate(this.candidates.shift())
}
}
}
get readyToMakeOffer () {
return !this.makingOffer && this.peerConnection.signalingState === 'stable'
}
get readyToReceiveOffer () {
return !this.makingOffer && (
this.peerConnection.signalingState === 'stable' ||
this.isSettingRemoteAnswerPending
)
}
collides (description) {
return description.type === 'offer' && !this.readyToReceiveOffer
}
ignore (description) {
return !this.polite && this.collides(description)
}
initiateManualRollback() {
this.restart()
this.signaller.signal({
type: 'restart',
to: this.otherClient.id,
from: this.client.id
})
}
restart() {
this.stop()
this.start()
}
start () {
this.setupPeerConnection()
}
stop () {
this.makingOffer = false
this.isSettingRemoteAnswerPending = false
this.candidates = []
this.teardownPeerConnection()
this.otherClient.streaming = false
}
setupPeerConnection () {
this.peerConnection = new RTCPeerConnection(peerConnectionConfig)
this._onnegotiationneeded = () => this.createOffer()
this._onicecandidate = ({ candidate }) => {
this.signaller.signal({
type: candidate ? 'candidate' : undefined,
to: this.otherClient.id,
from: this.client.id,
candidate
})
}
this._oniceconnectionstatechange = (event) => {
this.client.broadcast(`iceConnection:${this.peerConnection.iceConnectionState}`, { otherClient: this.otherClient })
switch (this.peerConnection.iceConnectionState) {
case 'completed':
this.retryCount = 0
break;
case 'failed':
if ('restartIce' in this.peerConnection) this.peerConnection.restartIce()
break;
default:
return
}
}
this._ontrack = (event) => this.otherClient.broadcast('track', event)
this.peerConnection.addEventListener('negotiationneeded', this._onnegotiationneeded)
this.peerConnection.addEventListener('icecandidate', this._onicecandidate)
this.peerConnection.addEventListener('iceconnectionstatechange', this._oniceconnectionstatechange)
this.peerConnection.addEventListener('track', this._ontrack)
}
teardownPeerConnection () {
this.peerConnection.close()
this.peerConnection.removeEventListener('negotiationneeded', this._onnegotiationneeded)
this.peerConnection.removeEventListener('icecandidate', this._onicecandidate)
this.peerConnection.removeEventListener('iceconnectionstatechange', this._oniceconnectionstatechange)
this.peerConnection.removeEventListener('track', this._ontrack)
this.peerConnection = null
}
}

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -0,0 +1,35 @@
import { cable } from '@hotwired/turbo-rails'
export default class SignalingSubscription {
constructor({ delegate, id, clientId }) {
this.callbacks = {}
this.delegate = delegate
this.id = id
this.clientId = clientId
}
async start () {
const self = this
this.subscription = await cable.subscribeTo({
channel: 'SignalingChannel',
id: this.id
}, {
received (data) {
const { to, from, type, description, candidate } = data
if (to != self.clientId) return
if (description) return self.delegate.sdpDescriptionReceived({ from, description })
if (candidate) return self.delegate.iceCandidateReceived({ from, candidate })
if (type === 'restart') return self.delegate.negotiationRestarted({ from })
}
})
this.started = true
}
signal (data) {
if (!this.started) return
this.subscription.perform('signal', data)
}
}

View File

@ -0,0 +1,36 @@
import { cable } from '@hotwired/turbo-rails'
export default class VideoRoomSubscription {
constructor ({ delegate, id, clientId }) {
this.delegate = delegate
this.id = id
this.clientId = clientId
}
async start () {
const self = this
this.subscription = await cable.subscribeTo({
channel: 'VideoRoomChannel',
id: this.id,
client_id: this.clientId
}, {
greet (data) {
this.perform('greet', data)
},
received (data) {
// Ignore self-sent data
if (data.from === self.clientId) return
if (data.type === 'ping') self.delegate.videoRoomPinged(data) }
})
this.started = true
}
greet (data) {
if (!this.started) return
this.subscription.greet(data)
}
}

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -1,18 +1,3 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any styles
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
* file per style scope.
*
*= require_tree .
*= require_self
*/
html
box-sizing: border-box
@ -28,17 +13,42 @@ body
margin: 0
background: image-url('backgrounds/felt-green.png')
font-size: 2vmin
// overflow: hidden
body, .social-links, .social-link a
text-shadow: -1px 1px #e1b027, 1px -1px #00ddff
a
text-decoration: none
color: white
color: #e7dede
outline: none
&:hover
color: gold
p
font-family: sans
text-shadow: none
b
font-family: "Anton", Impact, fantasy, sans-serif
text-shadow: -1px 1px #e1b027, 1px -1px #00ddff
h1
font-size: 7vmin
margin: 0 0 5vmin 0
margin-bottom: 0
font-family: "Press Start 2P", "Anton", Impact, fantasy, sans-serif
// h2
margin-bottom: 0
a
text-shadow: none
header
.home-link
font-family: "Press Start 2P", "Anton", Impact, fantasy, sans-serif
margin-left: 0
padding-left: 0
align-self: start
font-size: 3vmin
// margin-bottom: 10vmin
nav
@ -53,9 +63,12 @@ header
ul
margin: 0
display: flex
padding-left: 1em
li
flex: 1 1 auto
text-align: center
&:nth-child(even)
align-self: end
#content
flex: 3 1 auto
@ -64,11 +77,21 @@ header
flex-direction: column
flex-wrap: wrap
align-items: center
background: #00ff0060
border-radius: 0 13em 0 0
font-size: 2em
> h1
align-self: start
// padding-top: .6em
// text-indent: .4em
#home-headline
#home-headline, .home-headline
margin-top: 6em
flex: 1 1 auto
text-align: center
z-index: 10
cursor: pointer
h1
font-size: 10vmin
color: #111
@ -76,26 +99,172 @@ header
padding: 5vmin
margin: 0
border: 3px solid black
background-color: #33cc3399
text-shadow: -3px 3px #e1b027, 3px -3px #00ddff
line-height: 1.3em
#main-menu
flex: 1 1 auto
font-size: 5vmin
display: flex
flex-direction: column
z-index: 10
background: #00ff33
background: #00000066
border-radius: 100px 100px 0 0
padding: 2em
a
display:inline
background: green
margin: 4px 0 4px
padding: 8px
border: 2px solid black
text-align: center
&:hover
background: #bada55
color: black
background: #ffffff44
color: yellow
&:active
background: (#bada55 + 100)
*, *:before, *:after
box-sizing: inherit
font-weight: lighter
body
font-family: "Anton", Impact, fantasy, sans-serif
.eyecandy
display: block
left: 0
position: absolute
top: 0
// background-color: hotpink
border-radius: 10em
overflow: hidden
&.icypepe
// zoom: 70%
border-radius: 600em
padding: 1em 5em 1em 2em
cursor: pointer
transition: background-color 0.2s, box-shadow 0.2s
svg
// zoom: 80%
&:hover
background-color: gold
box-shadow: 1px 1px 8px 4px gold
img
cursor: pointer
transition: background-color 0.2s, box-shadow 0.2s
&:hover
background-color: gold
box-shadow: 1px 1px 8px 4px gold
img
width: 4rem
padding: 0.2em
&.clicked
img, &.icypepe
background-color: #00ffff
box-shadow: 0px 0px 8px 4px #00ffff
li
list-style: none
.alert
padding: 1em
background: #ffffff77
font-size: 1.2rem
color: #ffffff
text-shadow: 0 0 3px black
letter-spacing: 0.3
footer
padding: 2em 3em
text-align: right
background: #00000066
a
img
width: 4em
height: 4em
.footer-tokens
text-align: left
a
padding: 2em
background: #e1b02733
box-shadow: 0px 0px 8px #00000042
border-radius: 12em
display: inline-block
#skyspaces
width: 100%
height: 100%
.hide
display: none
.video-cover
position: absolute
z-index: 2
top: 0
left: 0
width: 100%
height: 100%
#videoplayer
position: absolute
z-index: 1
top: 0
left: 0
width: 100%
height: 100%
object-fit: fill
// form
width: 100%
padding: 1em
textarea
width: 100%
min-height: 8em
padding: 5em
overflow: hidden
border-radius: 0 8em 0 8em
.navigation-wallet
// font-family: "Press Start 2P", "Anton", Impact, fantasy, sans-serif
h1
font-size: 1em
margin-top: 0
line-height: 2em
font-size: 0.7em
text-align: right
padding: 0.5em
background: #00ff0060
border-radius: 0 0 0 79em
word-wrap: break-word
h2
font-size: 1em
margin: 0
padding: 0
span
font-family: monospace, monospace
text-shadow: none
color: #111
// font-family: "Press Start 2P", "Anton", Impact, fantasy, sans-serif
.contain
width: 100%
max-width: 1200px
margin: 0 auto
padding-left: .33em
.table-container
max-width: 100%
overflow-x: auto
align-self: start
@import doodads
@import profiles
@import tokens
@import microposts
@import projects
@import rooms
@import tables
@import game

View File

@ -0,0 +1,3 @@
// Place all the styles related to the Bots controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: https://sass-lang.com/

View File

@ -0,0 +1,3 @@
// Place all the styles related to the Calls controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: https://sass-lang.com/

View File

@ -0,0 +1,3 @@
// Place all the styles related to the Commands controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: https://sass-lang.com/

View File

@ -0,0 +1,12 @@
.doodad
word-wrap: break-word
padding: 1em
background: darkgoldenrod
box-shadow: 0px -2px 8px black
.doodads-view
form
width: 100%
padding: 1em

View File

@ -30,6 +30,8 @@
button,
input[type=submit]
font-size: 4vmin
&.smallbtn
font-size: 2vmin
#table-component,
#game-component-container-container

View File

@ -0,0 +1,30 @@
// .micropost_form
textarea
transition: 1s all
&:focus
color: #ddd
box-shadow: 0px 0px 0px 10px black inset, 0px 0px 0px 43px white inset, 0px 0px 116px 62px black inset
rotate: -36deg
ol.microposts
padding: 0
.micropost
.display-name, .timestamp, .delete
font-family: "Press Start 2P", "Anton", Impact, fantasy, sans-serif
font-size: .4em
margin: 1em
padding: 1em
background: #ffffff33
.content
font-family: sans
font-size: .8em
text-shadow: none
.delete
&.emoji
font-size: .6em
a
text-shadow: -1px 1px #e1b027, 1px -1px #00ddff
&.text a
color: #cc0000
text-shadow: -1px 1px #e1b027, 1px -1px #00ddff
// a
color: #111111

View File

@ -0,0 +1,56 @@
.profile
text-align: center
background: #ffffff33
border-radius: 1rem
padding: .8em 1em .6em 1em
margin: 1em
border: .1rem solid #333333
transition: background-color .2s, border-color .2s, box-shadow .2s, color .2s
h1
line-height: 1
p
line-height: 1.2
h1, p, span
margin: 0
a.profile
display: block
&:hover
background: #ffffff55
span, p, .social-links
color: black
.social-links
width: 100%
text-align: center
position: relative
background: #40a10b
background: linear-gradient(90deg, rgba(0,0,0,0) 0%, #e1b02777 47%, rgba(0, 0, 0, 0) 95%)
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-evenly;
// padding-bottom: .3em
> a
padding: 0 1em
.dscvr-logo, .x-logo
width: 1em
vertical-align: middle
.controls
a
font-size: 0.6em
.about
background: #34b134
background: image-url('backgrounds/felt-green.png')
width: 100%
color: #019d01
background: #031804
text-shadow: none
h2
text-align: center
color: #000
text-shadow: -1px 1px #e1b027, 1px -1px #00ddff
p
text-shadow: 0px 0px 2px #34b134
font-family: "sans"

View File

@ -0,0 +1,10 @@
.projects-index
.project
text-align: center
&:hover h1
text-shadow: 0px 0px 9px #e1b027
h1
text-shadow: -1px 1px #e1b027, 1px -1px #00ddff
transition: .15s text-shadow
p
margin-top: 0

View File

@ -0,0 +1,3 @@
// Place all the styles related to the Relationships controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: https://sass-lang.com/

View File

@ -0,0 +1,14 @@
#messages
font-family: sans-serif
width: 100%
.message
background: #ffffff44
padding: 0.2em
margin: 0.2em 0
h6
margin: 0
.from_name
padding: 0.15em
color: #aaa
text-shadow: none

View File

View File

@ -2,6 +2,10 @@
width: 100%
height: 100%
.owner-controls
form
display: inline-block
#table-controls
text-align: right
padding: 0 1em
@ -10,14 +14,16 @@
#qrcode
float: right
margin-top: -.5em
margin-right: 1em
margin-top: -7em
margin-right: 1.25em
transform: scale(10%)
transition: all 0.5s ease-in-out
transition: all 0.25s ease-out
width: 38px
height: 38px
&.full
margin-right: 2em
margin-top: -6em
margin-right: 0
margin-bottom: 1em
transform: scale(100%)
width: 384px
height: 384px

View File

@ -0,0 +1,18 @@
.token-logo
max-width: 100%
width: 4.20rem
.table-container
background: #39272799
width: 100%
table.token-index
font-family: "monospace"
font-size: 1.2rem
text-shadow: none
color: #aaaaaa
.token-logo
max-width: 4rem
vertical-align: middle
.token-show
font-size: 1rem

BIN
app/assets/videos/video.mp4 Normal file

Binary file not shown.

View File

@ -0,0 +1,4 @@
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end

View File

@ -0,0 +1,15 @@
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_client
def connect
self.current_client = find_client
end
private
def find_client
Client.new(id: cookies.encrypted[:client_id])
end
end
end

View File

@ -0,0 +1,9 @@
class CallChannel < ApplicationCable::Channel
def subscribed
stream_from "call_channel"
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end

View File

@ -0,0 +1,9 @@
class SignalingChannel < ApplicationCable::Channel
def subscribed
stream_for VideoRoom.new(id: params[:id])
end
def signal(data)
broadcast_to(VideoRoom.new(id: params[:id]), data)
end
end

View File

@ -0,0 +1,29 @@
class VideoRoomChannel < ApplicationCable::Channel
def subscribed
@video_room = find_video_room
stream_for @video_room
broadcast_to @video_room, { type: 'ping', from: params[:client_id] }
end
def unsubscribed
Turbo::StreamsChannel.broadcast_remove_to(
find_video_room,
target: "medium_#{current_client.id}"
)
end
def greet(data)
Turbo::StreamsChannel.broadcast_append_to(
data['to'],
target: 'media',
partial: 'media/medium',
locals: { client_id: data['from'] }
)
end
private
def find_video_room
VideoRoom.new(id: params[:id])
end
end

View File

@ -1,25 +1,31 @@
class ApplicationController < ActionController::Base
include Pundit::Authorization
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
# protect_from_forgery with: :exception
protect_from_forgery unless: -> { request.format.json? }
# skip_before_action :verify_authenticity_token
after_action :flash_to_http_header
before_action :get_footer_tokens
before_action :get_global_doodads
if (Rails.env.development? || Rails.env.test?)
# https://github.com/RailsApps/rails-devise-pundit/issues/10
include Pundit
# https://github.com/elabs/pundit#ensuring-policies-are-used
#after_action :verify_authorized, except: :index
#after_action :verify_policy_scoped, only: :index
# if (Rails.env.development? || Rails.env.test?)
after_action :verify_authorized, unless: -> { devise_controller? }
# after_action :verify_policy_scoped, only: :index
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
private
def user_not_authorized
flash[:alert] = 'Access denied.'
def user_not_authorized(exception)
policy_name = exception.policy.class.to_s.underscore
# flash[:alert] = "#{policy_name}.#{exception.query}"
flash[:error] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default
if flash[:error] == "You cannot perform this action."
flash[:error] = "Unable to #{exception.query[0..-2]} #{policy_name.split("_")[0].capitalize}"
end
redirect_to (request.referrer || root_path)
end
end
# end
def authenticate_user!(args = nil)
current_user.present?
@ -31,6 +37,19 @@ class ApplicationController < ActionController::Base
private
def add_body_css_class(css_class)
@body_css_classes ||= []
@body_css_classes << css_class
end
def get_footer_tokens
@footer_tokens = policy_scope(Token)
end
def get_global_doodads
@global_doodads = policy_scope(Doodad).where(is_global: true)
end
def flash_to_http_header
return unless request.xhr?
return if flash.empty?

View File

@ -0,0 +1,80 @@
class BotsController < ApplicationController
before_action :set_bot, only: %i[ show edit update destroy telegram_listen ]
# GET /bots or /bots.json
def index
authorize @bots = policy_scope(Bot)
end
# GET /bots/1 or /bots/1.json
def show
authorize @bot
end
# GET /bots/new
def new
authorize @bot = current_user.bots.new
end
# GET /bots/1/edit
def edit
authorize @bot
end
def telegram_listen
authorize @bot
# TODO enable bots with job scheduler
# @bot.delay.telegram_listen
redirect_to request.referrer
end
# POST /bots or /bots.json
def create
authorize @bot = Bot.new(bot_params)
respond_to do |format|
if @bot.save
format.html { redirect_to bot_url(@bot), notice: "Bot was successfully created." }
format.json { render :show, status: :created, location: @bot }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @bot.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /bots/1 or /bots/1.json
def update
authorize @bot
respond_to do |format|
if @bot.update(bot_params)
format.html { redirect_to bot_url(@bot), notice: "Bot was successfully updated." }
format.json { render :show, status: :ok, location: @bot }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @bot.errors, status: :unprocessable_entity }
end
end
end
# DELETE /bots/1 or /bots/1.json
def destroy
@bot.destroy
respond_to do |format|
format.html { redirect_to bots_url, notice: "Bot was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_bot
@bot = Bot.find(params[:id])
end
# Only allow a list of trusted parameters through.
def bot_params
params.require(:bot).permit(:name, :telegram_api_token, :discord_api_token, :user_id, :profile_id)
end
end

View File

@ -0,0 +1,12 @@
class CallsController < ApplicationController
before_action :skip_authorization
def create
head :no_content
ActionCable.server.broadcast("call_channel", call_params)
end
private
def call_params
params.permit(:call, :type, :from, :to, :sdp, :candida)
end
end

View File

@ -0,0 +1,73 @@
class CanistersController < ApplicationController
before_action :set_canister, only: %i[ show edit update destroy ]
# GET /canisters or /canisters.json
def index
authorize @canisters = policy_scope(Canister)
end
# GET /canisters/1 or /canisters/1.json
def show
authorize @canister
end
# GET /canisters/new
def new
authorize @canister = current_user.canisters.new
end
# GET /canisters/1/edit
def edit
authorize @canister
end
# POST /canisters or /canisters.json
def create
authorize @canister = Canister.new(canister_params)
respond_to do |format|
if @canister.save
format.html { redirect_to @canister, notice: "Canister was successfully created." }
format.json { render :show, status: :created, location: @canister }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @canister.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /canisters/1 or /canisters/1.json
def update
authorize @canister
respond_to do |format|
if @canister.update(canister_params)
format.html { redirect_to @canister, notice: "Canister was successfully updated." }
format.json { render :show, status: :ok, location: @canister }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @canister.errors, status: :unprocessable_entity }
end
end
end
# DELETE /canisters/1 or /canisters/1.json
def destroy
authorize @canister
@canister.destroy
respond_to do |format|
format.html { redirect_to canisters_url, notice: "Canister was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_canister
@canister = Canister.find(params[:id])
end
# Only allow a list of trusted parameters through.
def canister_params
params.require(:canister).permit(:icid, :name, :user_id)
end
end

View File

@ -0,0 +1,81 @@
class CommandsController < ApplicationController
before_action :set_command, only: %i[ show edit update destroy run ]
# GET /commands or /commands.json
def index
authorize @commands = Command.all
end
# GET /commands/1 or /commands/1.json
def show
authorize @command
end
# RUN /commands/1/run
def run
authorize @command
response_text = eval(@command.body)
redirect_to (request.referrer || @command), notice: response_text
end
# GET /commands/new
def new
@command = Command.new
end
# GET /commands/1/edit
def edit
authorize @command
end
# POST /commands or /commands.json
def create
@command = Command.new(command_params)
respond_to do |format|
if @command.save
format.html { redirect_to command_url(@command), notice: "Command was successfully created." }
format.json { render :show, status: :created, location: @command }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @command.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /commands/1 or /commands/1.json
def update
authorize @command
respond_to do |format|
if @command.update(command_params)
format.html { redirect_to command_url(@command), notice: "Command was successfully updated." }
format.json { render :show, status: :ok, location: @command }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @command.errors, status: :unprocessable_entity }
end
end
end
# DELETE /commands/1 or /commands/1.json
def destroy
@command.destroy
respond_to do |format|
format.html { redirect_to commands_url, notice: "Command was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_command
@command = Command.find(params[:id])
end
# Only allow a list of trusted parameters through.
def command_params
params.require(:command).permit(:name, :trigger, :body)
end
end

View File

@ -0,0 +1,73 @@
class DoodadsController < ApplicationController
before_action :set_doodad, only: %i[ show edit update destroy ]
# GET /doodads or /doodads.json
def index
authorize @doodads = policy_scope(Doodad)
end
# GET /doodads/1 or /doodads/1.json
def show
authorize @doodad
end
# GET /doodads/new
def new
authorize @doodad = current_user.doodads.new
end
# GET /doodads/1/edit
def edit
authorize @doodad
end
# POST /doodads or /doodads.json
def create
authorize @doodad = Doodad.new(doodad_params)
respond_to do |format|
if @doodad.save
format.html { redirect_to @doodad, notice: "Doodad was successfully created." }
format.json { render :show, status: :created, location: @doodad }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @doodad.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /doodads/1 or /doodads/1.json
def update
authorize @doodad
respond_to do |format|
if @doodad.update(doodad_params)
format.html { redirect_to @doodad, notice: "Doodad was successfully updated." }
format.json { render :show, status: :ok, location: @doodad }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @doodad.errors, status: :unprocessable_entity }
end
end
end
# DELETE /doodads/1 or /doodads/1.json
def destroy
authorize @doodad
@doodad.destroy
respond_to do |format|
format.html { redirect_to doodads_url, notice: "Doodad was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_doodad
@doodad = Doodad.find(params[:id])
end
# Only allow a list of trusted parameters through.
def doodad_params
params.require(:doodad).permit(:body, :user_id, :is_public, :is_global)
end
end

View File

@ -28,6 +28,7 @@ class GamesController < ApplicationController
end
def play_hand
authorize @game
# TODO: move this logic out of controller maybe to model(s) ?
# validate player's turn
@ -124,6 +125,7 @@ class GamesController < ApplicationController
end
def start
authorize @game
begin
@game.start
rescue StandardError => e

View File

@ -0,0 +1,13 @@
class MessagesController < ApplicationController
def create
@message = current_user.messages.build(content: msg_params[:content], room_id: params[:room_id])
authorize @message
@message.save
end
private
def msg_params
params.require(:message).permit(:content)
end
end

View File

@ -0,0 +1,90 @@
class MetapursesController < ApplicationController
before_action :set_metapurse, only: %i[ show edit update destroy data ]
# GET /metapurses or /metapurses.json
def index
authorize @metapurses = policy_scope(Metapurse)
end
# GET /metapurses/1 or /metapurses/1.json
def show
authorize @metapurse
end
def data
authorize @metapurse
end
# GET /metapurses/new
def new
authorize @metapurse = current_user.metapurses.new
@metapurse.data = "ryjl3-tyaaa-aaaaa-aaaba-cai 100 ICP
iozql-7iaaa-aaaah-advvq-cai 880 TENDIES
whdfs-saaaa-aaaao-awh4a-cai 240 NEED
ss2fx-dyaaa-aaaar-qacoq-cai 0.1 ckETH
nwd3n-qaaaa-aaaak-afmda-cai 192.92 INSANE
eayyd-iiaaa-aaaah-adtea-cai 5678.1234 iDoge
rh2pm-ryaaa-aaaan-qeniq-cai 69420.98 Windoge98 EXE
7tx3o-zyaaa-aaaak-aes6q-cai 1337456899999 DOGMI
wnnwu-4iaaa-aaaar-qacxq-cai 420690000 SKIBIDI
67mu5-maaaa-aaaar-qadca-cai 360 MCS
kz5t3-pyaaa-aaaap-ab2qq-cai 5000000 iVishnu"
end
# GET /metapurses/1/edit
def edit
authorize @metapurse
end
# POST /metapurses or /metapurses.json
def create
authorize @metapurse = Metapurse.new(metapurse_params)
respond_to do |format|
if @metapurse.save
format.html { redirect_to metapurse_url(@metapurse), notice: "Metapurse was successfully created." }
format.json { render :show, status: :created, location: @metapurse }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @metapurse.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /metapurses/1 or /metapurses/1.json
def update
authorize @metapurse
respond_to do |format|
if @metapurse.update(metapurse_params)
format.html { redirect_to metapurse_url(@metapurse), notice: "Metapurse was successfully updated." }
format.json { render :show, status: :ok, location: @metapurse }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @metapurse.errors, status: :unprocessable_entity }
end
end
end
# DELETE /metapurses/1 or /metapurses/1.json
def destroy
authorize @metapurse
@metapurse.destroy!
respond_to do |format|
format.html { redirect_to metapurses_url, notice: "Metapurse was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_metapurse
@metapurse = Metapurse.find(params[:id])
end
# Only allow a list of trusted parameters through.
def metapurse_params
params.require(:metapurse).permit(:name, :data, :user_id, :is_private)
end
end

View File

@ -0,0 +1,33 @@
class MicropostsController < ApplicationController
before_action :set_micropost, only: %i[ show edit update destroy ]
def create
@micropost = Micropost.new(micropost_params)
authorize @micropost
if @micropost.save
flash[:success] = "Post created!"
redirect_to request.referrer || root_url
else
flash[:error] = "Post failed!"
redirect_to request.referrer || root_url
end
end
def destroy
authorize @micropost
@micropost.destroy
respond_to do |format|
format.html { redirect_to request.referrer || root_url, notice: "Post was deleted." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_micropost
@micropost = Micropost.find(params[:id])
end
def micropost_params
params.require(:micropost).permit(:content, :micropostable_type, :micropostable_id)
end
end

View File

@ -0,0 +1,5 @@
class PagesController < ApplicationController
before_action :skip_authorization
def czechers
end
end

View File

@ -0,0 +1,81 @@
class ProfilesController < ApplicationController
before_action :set_profile, only: %i[ show edit update destroy ]
# GET /profiles or /profiles.json
def index
@profiles = policy_scope Profile.all
authorize @profiles
end
# GET /profiles/1 or /profiles/1.json
def show
authorize @profile
@followable = @profile
if @profile.user == current_user
@micropost = @profile.microposts.build
else
@micropost = current_user.microposts.build if current_user.signed_in?
end
@microposts = @profile.microposts.paginate(page: params[:page])
end
# GET /profiles/new
def new
authorize @profile = current_user.profiles.new
end
# GET /profiles/1/edit
def edit
authorize @profile
end
# POST /profiles or /profiles.json
def create
authorize @profile = Profile.new(profile_params)
respond_to do |format|
if @profile.save
format.html { redirect_to profile_url(@profile), notice: "Profile was successfully created." }
format.json { render :show, status: :created, location: @profile }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @profile.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /profiles/1 or /profiles/1.json
def update
authorize @profile
respond_to do |format|
if @profile.update(profile_params)
format.html { redirect_to profile_url(@profile), notice: "Profile was successfully updated." }
format.json { render :show, status: :ok, location: @profile }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @profile.errors, status: :unprocessable_entity }
end
end
end
# DELETE /profiles/1 or /profiles/1.json
def destroy
@profile.destroy
respond_to do |format|
format.html { redirect_to profiles_url, notice: "Profile was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_profile
@profile = Profile.find(params[:id])
end
# Only allow a list of trusted parameters through.
def profile_params
params.require(:profile).permit(:user_id, :name, :summary, :about)
end
end

View File

@ -0,0 +1,76 @@
class ProjectsController < ApplicationController
before_action :set_project, only: %i[ show edit update destroy ]
# GET /projects or /projects.json
def index
@projects = authorize Project.all
end
# GET /projects/1 or /projects/1.json
def show
authorize @project
@followable = @project
if @project.user == current_user
@micropost = @project.microposts.build
end
end
# GET /projects/new
def new
authorize @project = current_user.projects.new
end
# GET /projects/1/edit
def edit
authorize @project
end
# POST /projects or /projects.json
def create
authorize @project = Project.new(project_params)
respond_to do |format|
if @project.save
format.html { redirect_to project_url(@project), notice: "Project was successfully created." }
format.json { render :show, status: :created, location: @project }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @project.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /projects/1 or /projects/1.json
def update
respond_to do |format|
if @project.update(project_params)
format.html { redirect_to project_url(@project), notice: "Project was successfully updated." }
format.json { render :show, status: :ok, location: @project }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @project.errors, status: :unprocessable_entity }
end
end
end
# DELETE /projects/1 or /projects/1.json
def destroy
@project.destroy
respond_to do |format|
format.html { redirect_to projects_url, notice: "Project was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_project
@project = Project.find(params[:id])
end
# Only allow a list of trusted parameters through.
def project_params
params.require(:project).permit(:title, :description, :user_id)
end
end

View File

@ -0,0 +1,16 @@
class RelationshipsController < ApplicationController
def create
authorize Relationship
leader = params[:followable_type].constantize.find(params[:followable_id])
current_user.follow(leader)
redirect_to leader
end
def destroy
relationship = Relationship.find(params[:id])
authorize relationship
leader = relationship.followable
current_user.unfollow(leader)
redirect_to leader
end
end

View File

@ -0,0 +1,31 @@
class RoomsController < ApplicationController
before_action :set_room, only: %i[ show edit update destroy ]
def index
@rooms = policy_scope Room.all
authorize @rooms
authorize @new_room = Room.new
end
def create
authorize @room = Room.build(name: params["room"]["name"])
@room.save
end
def show
authorize @room
@rooms = Room.public_rooms
@message = Message.new
@messages = @room.messages
@new_room = Room.new
render "index"
end
private
# Use callbacks to share common setup or constraints between actions.
def set_room
@room = Room.find(params[:id])
end
end

View File

@ -44,6 +44,7 @@ class SeatsController < ApplicationController
# PATCH/PUT /seats/1
# PATCH/PUT /seats/1.json
def update
authorize @seat
respond_to do |format|
if @seat.update(seat_params)
format.html { redirect_to @seat, notice: 'Seat was successfully updated.' }
@ -58,6 +59,7 @@ class SeatsController < ApplicationController
# DELETE /seats/1
# DELETE /seats/1.json
def destroy
authorize @seat
@seat.destroy
respond_to do |format|
format.html { redirect_to seats_url, notice: 'Seat was successfully destroyed.' }
@ -67,6 +69,7 @@ class SeatsController < ApplicationController
# POST /seats/1
def sit
authorize @seat
@message = @seat.sit current_user
respond_to do |format|
if @seat.save
@ -78,11 +81,13 @@ class SeatsController < ApplicationController
end
def stand
authorize @seat
@message = @seat.stand current_user
redirect_to @seat.table, notice: @message
end
def add_bot
authorize @seat
@message = @seat.add_bot
redirect_to @seat.table, notice: @message
end
@ -93,11 +98,13 @@ class SeatsController < ApplicationController
end
def empty
authorize @seat
@message = @seat.empty
redirect_to @seat.table, notice: @message
end
def remove_player
authorize @seat
@message = @seat.remove_player
redirect_to @seat.table, notice: @message
end

View File

@ -0,0 +1,77 @@
class SocialLinksController < ApplicationController
before_action :set_social_link, only: %i[ show edit update destroy ]
# GET /social_links or /social_links.json
def index
@social_links = policy_scope SocialLink.all
authorize @social_links
end
# GET /social_links/1 or /social_links/1.json
def show
authorize @social_link
end
# GET /social_links/new
def new
@social_link = SocialLink.new
@social_link.profile_id = params[:profile_id] if params[:profile_id]
authorize @social_link
end
# GET /social_links/1/edit
def edit
authorize @social_link
end
# POST /social_links or /social_links.json
def create
authorize @social_link = SocialLink.new(social_link_params)
respond_to do |format|
if @social_link.save
format.html { redirect_to @social_link.profile, notice: "Social link was successfully created." }
format.json { render :show, status: :created, location: @social_link }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @social_link.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /social_links/1 or /social_links/1.json
def update
authorize @social_link
respond_to do |format|
if @social_link.update(social_link_params)
format.html { redirect_to @social_link.profile, notice: "Social link was successfully updated." }
format.json { render :show, status: :ok, location: @social_link }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @social_link.errors, status: :unprocessable_entity }
end
end
end
# DELETE /social_links/1 or /social_links/1.json
def destroy
authorize @social_link
@social_link.destroy
respond_to do |format|
format.html { redirect_to social_links_url, notice: "Social link was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_social_link
@social_link = SocialLink.find(params[:id])
end
# Only allow a list of trusted parameters through.
def social_link_params
params.require(:social_link).permit(:profile_id, :url)
end
end

View File

@ -7,9 +7,10 @@ class TablesController < ApplicationController
# First empty seat
@seat = Seat.where(user_soft_token: nil).select{|s| !s.player.try("is_bot?")}.first
if @seat
authorize @seat
@seat.sit current_user
else
@table = Table.create(title: "Table " + current_user.soft_token[0..4])
authorize @table = Table.create(title: "Table " + current_user.soft_token[0..4])
@seat = @table.seats.first
@seat.sit current_user
end
@ -24,23 +25,27 @@ class TablesController < ApplicationController
# GET /tables
# GET /tables.json
def index
@tables = Table.all
@tables = authorize Table.all
end
# GET /tables/1
# GET /tables/1.json
def show
# TODO refactor to ensure play for 2nd and 3rd place
authorize @table
if @game
authorize @game
# TODO refactor to ensure play for 2nd and 3rd place
if @game.controlling_player.try("is_bot?")
@game.controlling_player.auto_play
@game.save
@game.reload
if @game.controlling_player.try("is_bot?")
@game.controlling_player.auto_play
@game.save
@game.reload
end
end
end
def new_game
authorize @table
@game = @table.add_game
begin
@game.start
@ -57,17 +62,18 @@ class TablesController < ApplicationController
# GET /tables/new
def new
@table = Table.new
authorize @table = Table.new
end
# GET /tables/1/edit
def edit
authorize @table
end
# POST /tables
# POST /tables.json
def create
@table = Table.new(table_params)
authorize @table = Table.new(table_params)
respond_to do |format|
if @table.save
@ -83,6 +89,7 @@ class TablesController < ApplicationController
# PATCH/PUT /tables/1
# PATCH/PUT /tables/1.json
def update
authorize @table
respond_to do |format|
if @table.update(table_params)
format.html { redirect_to @table, notice: 'Table was successfully updated.' }
@ -97,6 +104,7 @@ class TablesController < ApplicationController
# DELETE /tables/1
# DELETE /tables/1.json
def destroy
authorize @table
@table.destroy
respond_to do |format|
format.html { redirect_to tables_url, notice: 'Table was successfully destroyed.' }
@ -107,13 +115,14 @@ class TablesController < ApplicationController
private
# Use callbacks to share common setup or constraints between actions.
def set_table
@table = Table.find(params[:id])
# @table = Table.find(params[:id])
@table = Table.friendly.find(params[:id])
@game = @table.current_game
@seats = @table.seats.order(:id)
end
# Never trust parameters from the scary internet, only allow the white list through.
def table_params
params.require(:table).permit(:title)
params.require(:table).permit(:title, :token_id)
end
end

View File

@ -0,0 +1,135 @@
class TokensController < ApplicationController
before_action :set_token, only: %i[ show edit update destroy refresh launch]
# GET /tokens or /tokens.json
def index
authorize @tokens = Token.all
@mytokens = Token.where(ownable_id: current_user.soft_token)
end
# GET /tokens/1 or /tokens/1.json
def show
authorize @token
end
# GET /tokens/new
def new
authorize @token = Token.new(ownable_id: current_user.soft_token)
end
def add_existing
authorize @token = Token.new
end
# GET /tokens/1/edit
def edit
authorize @token
end
def launch
authorize @token
redirect_to @token, notice: "Launch function coming soon!"
end
def refresh
authorize @token
# if call icrc1_metadata #icrc1
metadata = `dfx canister --network ic call #{@token.canister_id} icrc1_metadata 2>&1`
if metadata.scan(/no update method/).present?
# TODO: Use getTokenInfo instead of getMetadata
metadata = `dfx canister --network ic call #{@token.canister_id} getMetadata 2>&1`
if metadata.scan(/no update method/).present?
@token.standard = :unknown
else
@token.standard = :dip20
# TODO: Use getTokenInfo instead of getMetadata
tokenInfo = `dfx canister --network ic call #{@token.canister_id} getTokenInfo 2>&1`
@token.holder_number = tokenInfo.lines[2].split[2]
@token.transfer_fee = metadata.lines[2].split[2].to_i
@token.decimals = metadata.lines[3].split[2]
# @token.owner = metadata.lines[4].split[3]
# @token.logo_url = metadata.lines[5].split("\"")[1]
@token.logo_url = tokenInfo.lines[8].split[2].split('"')[1]
@token.name = metadata.lines[6].split("\"")[1]
@token.total_supply = metadata.lines[7].split[2].to_i/(10.0**@token.decimals)
@token.symbol = metadata.lines[8].split("\"")[1]
end
else
@token.standard = :icrc1
@token.transfer_fee = metadata.lines[2].split[7].to_i
@token.decimals = metadata.lines[5].split[7].to_i
begin
@token.logo_url = metadata.lines[9].split("\"")[1]
rescue
end
@token.name = metadata.lines[3].split("\"")[3]
total_supply = `dfx canister --network ic call #{@token.canister_id} icrc1_total_supply 2>&1`
@token.total_supply = total_supply.split[0][1..-1].to_i/(10.0**@token.decimals)
@token.symbol = metadata.lines[4].split("\"")[3]
end
# elsif call getMetadata #dip20
respond_to do |format|
if @token.save
format.html { redirect_to token_url(@token), notice: "Token was successfully refreshed." }
format.json { render :show, status: :created, location: @token }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @token.errors, status: :unprocessable_entity }
end
end
end
# POST /tokens or /tokens.json
def create
authorize @token = Token.new(token_params)
@token.canister_id = nil if @token.canister_id.blank?
respond_to do |format|
if @token.save
format.html { redirect_to (request.referrer.split("/")[-1].match("add_existing") ? refresh_token_url(@token) : @token), notice: "Token was successfully created." }
format.json { render :show, status: :created, location: @token }
else
format.html { render (request.referrer.split("/")[-1].match("add_existing") ? :add_existing : :new), status: :unprocessable_entity }
format.json { render json: @token.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tokens/1 or /tokens/1.json
def update
authorize @token
@token.canister_id = nil if @token.canister_id.blank?
respond_to do |format|
if @token.update(token_params)
format.html { redirect_to token_url(@token), notice: "Token was successfully updated." }
format.json { render :show, status: :ok, location: @token }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @token.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tokens/1 or /tokens/1.json
def destroy
authorize @token
@token.destroy
respond_to do |format|
format.html { redirect_to tokens_url, notice: "Token was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_token
@token = Token.find(params[:id])
end
# Only allow a list of trusted parameters through.
def token_params
params.require(:token).permit(:canister_id, :standard, :symbol, :name, :total_supply, :decimals, :transfer_fee, :logo_url, :ownable_id)
end
end

View File

@ -3,15 +3,28 @@ class UsersController < ApplicationController
after_action :verify_authorized
def index
@users = User.all
authorize User
@users = policy_scope User.all
authorize @users
end
def show
@user = User.find(params[:id])
@user ||= User.find(params[:id])
@micropost = current_user.microposts.build if current_user.signed_in?
@microposts = @user.microposts.paginate(page: params[:page])
authorize @user
end
def home
authorize current_user
@user = current_user
@micropost = current_user.microposts.build if current_user.signed_in?
@microposts = @user.microposts.paginate(page: params[:page])
@feed_items = current_user.feed.paginate(page: params[:page], per_page: 10)
# authorize @user
# redirect_to current_user
end
def update
@user = User.find(params[:id])
authorize @user

View File

@ -0,0 +1,16 @@
class VideoRoomsController < ApplicationController
before_action :skip_authorization
def new
end
def create
redirect_to room_path(SecureRandom.uuid)
end
def show
@client = Client.new(id: SecureRandom.uuid)
cookies.encrypted[:client_id] = @client.id
@video_room = VideoRoom.new(id: params[:id])
end
end

View File

@ -1,2 +1,14 @@
class VisitorsController < ApplicationController
before_action :skip_authorization
def index
@doodads = authorize policy_scope(Doodad)
# todo Canister feature
# @canisters = authorize Canister.all
@feed_items = current_user.feed.paginate(page: params[:page])
end
def games_index
end
end

View File

@ -1,2 +1,106 @@
module ApplicationHelper
def body_css_class
@body_css_classes ||= []
# view_css_class = [controller_path.split('/'), action_name, 'view'].flatten.join('-')
view_css_class = [controller_path.split('/'), action_name, 'view'].flatten[0] + "-view"
@body_css_classes.unshift(view_css_class).join(' ')
end
def currency_balance(principal, currency_symbol, dfx_id = nil)
canisters = {
ICYPEES: "es3he-kyaaa-aaaah-abzna-cai",
EVL: "7wqow-haaaa-aaaao-ahbpq-cai",
"SNS-1": "zfcdd-tqaaa-aaaaq-aaaga-cai",
TENDY: "72uqs-pqaaa-aaaak-aes7a-cai",
YC: "5gxp5-jyaaa-aaaag-qarma-cai",
CZECH: "fkhzl-saaaa-aaaan-qd26a-cai",
ICL: "5573k-xaaaa-aaaak-aacnq-cai",
OT: "imeri-bqaaa-aaaai-qnpla-cai",
"01": "6ohjj-4qaaa-aaaai-aapua-cai",
BABYAROFdip20: "iy6hh-xaaaa-aaaan-qauza-cai"}
multipliers = {
TENDY: 100000000,
ICYPEES: 100000000,
CZECH: 100000000,
OT: 100000000,
EVL: 100000000,
"SNS-1": 100000000,
ICL: 100000000,
"01": 100000,
BABYAROFDIP20: 100000000
}
begin
# if currency_symbol == "ICL"
# binding.pry
# end
if ["SNS-1"].any?{ |s| s.casecmp(currency_symbol)==0 }
wallet_currency_balance = `dfx canister --network ic call #{canisters[:"#{currency_symbol}"]} #{currency_symbol == "SNS-1" ? "icrc1_balance_of" : "balanceOf"} '(record { owner = principal "#{principal}"})'`.gsub("_","").match(/\d+/)[0].to_f/(multipliers[:"#{currency_symbol}"])
elsif ["BTC"].any?{ |s| s.casecmp(currency_symbol)==0 }
puts "BTC"
`bitcoin-core.cli loadwallet #{dfx_id}`
wallet_currency_balance = `bitcoin-core.cli getbalance`.strip
if wallet_currency_balance.to_s.empty?
`bitcoin-core.cli createwallet "#{dfx_id}"`
`bitcoin-core.cli loadwallet #{dfx_id}`
end
wallet_currency_balance = `bitcoin-core.cli getbalance`.strip
`bitcoin-core.cli unloadwallet #{dfx_id}`
elsif ["testBTC"].any?{ |s| s.casecmp(currency_symbol)==0 }
puts "testBTC"
`bitcoin-core.cli loadwallet #{dfx_id}`
wallet_currency_balance = `bitcoin-core.cli -testnet getbalance`.strip
if wallet_currency_balance.to_s.empty?
`bitcoin-core.cli -testnet createwallet "#{dfx_id}"`
end
`bitcoin-core.cli -testnet loadwallet #{dfx_id}`
wallet_currency_balance = `bitcoin-core.cli -testnet getbalance`.strip
`bitcoin-core.cli -testnet unloadwallet #{dfx_id}`
elsif ["ICP"].any?{ |s| s.casecmp(currency_symbol)==0 }
wallet_currency_balance = icp_balance(dfx_id)
elsif ["ETH"].any?{ |s| s.casecmp(currency_symbol)==0 }
wallet_currency_balance = `eth address:balance -n mainnet #{dfx_id}`.strip
if wallet_currency_balance.empty?
new_address = JSON.parse `eth address:random`
`eth address:add #{dfx_id} #{new_address["privateKey"]}`
wallet_currency_balance = `eth address:balance -n mainnet #{dfx_id}`.strip
end
elsif ["goerliBaseETH"].any?{ |s| s.casecmp(currency_symbol)==0 }
wallet_currency_balance = `eth address:balance -n goerliBase #{dfx_id}`.strip
if wallet_currency_balance.empty?
new_address = JSON.parse `eth address:random`
`eth address:add #{dfx_id} #{new_address["privateKey"]}`
wallet_currency_balance = `eth address:balance -n goerliBase #{dfx_id}`.strip
end
elsif ["goerliETH"].any?{ |s| s.casecmp(currency_symbol)==0 }
wallet_currency_balance = `eth address:balance -n goerli #{dfx_id}`.strip
if wallet_currency_balance.empty?
new_address = JSON.parse `eth address:random`
`eth address:add #{dfx_id} #{new_address["privateKey"]}`
wallet_currency_balance = `eth address:balance -n goerli #{dfx_id}`.strip
end
elsif ["sepETH"].any?{ |s| s.casecmp(currency_symbol)==0 }
wallet_currency_balance = `eth address:balance -n sep #{dfx_id}`.strip
if wallet_currency_balance.empty?
new_address = JSON.parse `eth address:random`
`eth address:add #{dfx_id} #{new_address["privateKey"]}`
wallet_currency_balance = `eth address:balance -n sep #{dfx_id}`.strip
end
elsif canisters.keys.map{|k| k.to_s}.any?{ |s| s.casecmp(currency_symbol)==0 }
# binding.pry
wallet_currency_balance = `dfx canister --network ic call #{canisters[:"#{currency_symbol.upcase}"]} balanceOf '(principal "#{principal}")'`.gsub("_","").match(/\d+/)[0].to_f/(multipliers[:"#{currency_symbol.upcase}"])
else
return "Currency not found"
end
rescue
return "Error fetching balance"
end
if wallet_currency_balance.to_s.empty?
return "Error fetching "
else
return wallet_currency_balance
end
end
end

View File

@ -0,0 +1,2 @@
module BotsHelper
end

View File

@ -0,0 +1,2 @@
module CallsHelper
end

View File

@ -0,0 +1,2 @@
module CanistersHelper
end

View File

@ -0,0 +1,2 @@
module CommandsHelper
end

View File

@ -0,0 +1,2 @@
module DoodadsHelper
end

View File

@ -0,0 +1,2 @@
module MetapursesHelper
end

View File

@ -0,0 +1,2 @@
module MicropostsHelper
end

View File

@ -0,0 +1,2 @@
module PagesHelper
end

View File

@ -0,0 +1,2 @@
module ProfilesHelper
end

View File

@ -0,0 +1,2 @@
module ProjectsHelper
end

View File

@ -0,0 +1,2 @@
module RelationshipsHelper
end

View File

@ -0,0 +1,2 @@
module RoomsHelper
end

View File

@ -0,0 +1,2 @@
module SocialLinksHelper
end

Some files were not shown because too many files have changed in this diff Show More