a mini social media app for small communities

update about page

+4
.gitignore
··· 1 1 # Binaries 2 2 /beep 3 3 /build/ 4 + /scripts/fetchbuildinfo 4 5 5 6 # Editor/system specific metadata 6 7 .DS_Store ··· 9 10 # Secrets 10 11 /config.real.maple 11 12 .env 13 + 14 + # Build data 15 + /buildinfo.maple 12 16 13 17 # Local V and Clockwork install (Gitpod) 14 18 /clockwork
+1 -1
Dockerfile
··· 40 40 41 41 STOPSIGNAL SIGINT 42 42 EXPOSE 8008 43 - CMD ["./beep", "./config.real.maple"] 43 + CMD ["./beep"]
+29 -12
build.maple
··· 1 1 plugins = [ 'v' ] 2 2 3 + task::fetch-build-info = { 4 + description = 'Fetch misc build information, mainly for the about page' 5 + run = 'v scripts/fetchbuildinfo.vsh' 6 + } 7 + 8 + // Database 9 + 3 10 task:db.init = { 4 11 description = 'Initialize and start a local Postgres database via Docker' 5 12 category = 'db' ··· 43 50 run = 'docker rm beep-database && docker volume rm beep-data' 44 51 } 45 52 53 + // Ngrok 54 + 46 55 task:ngrok = { 47 56 description = 'Open an ngrok tunnel for testing.' 48 57 category = 'misc' ··· 55 64 run = 'ngrok http --url=${args} http://localhost:8008' 56 65 } 57 66 67 + // Run 68 + 69 + task:run = { 70 + description = 'Run beep' 71 + category = 'run' 72 + depends = [':fetch-build-info'] 73 + run = '${v} run ${v_main} config.maple' 74 + } 75 + 76 + task:run.real = { 77 + description = 'Run beep using config.real.maple' 78 + category = 'run' 79 + depends = [':fetch-build-info'] 80 + run = '${v} run ${v_main}' 81 + } 82 + 58 83 task:run.watch = { 59 84 description = 'Watch/run beep' 60 85 category = 'run' 86 + depends = [':fetch-build-info'] 61 87 run = '${v} -d veb_livereload watch run ${v_main} config.maple' 62 88 } 63 89 64 90 task:run.watch.real = { 65 91 description = 'Watch/run beep using config.real.maple' 66 92 category = 'run' 67 - run = '${v} watch run ${v_main} config.real.maple' 68 - } 69 - 70 - task:run = { 71 - description = 'Run beep' 72 - category = 'run' 73 - run = '${v} run ${v_main} config.maple' 93 + depends = [':fetch-build-info'] 94 + run = '${v} watch run ${v_main}' 74 95 } 75 96 76 - task:run.real = { 77 - description = 'Run beep using config.real.maple' 78 - category = 'run' 79 - run = '${v} run ${v_main} config.real.maple' 80 - } 97 + // Misc 81 98 82 99 task:cloc = { 83 100 description = 'Get the lines of code for beep!'
+6
config.maple
··· 11 11 // Set this to '' if your instance is closed source. This is shown on the about page. 12 12 source = 'https://tangled.org/emmeline.girlkisser.top/beep' 13 13 14 + // Source for your V compiler. Unless you're using a fork of V, you shouldn't need to change this. 15 + v_source = 'https://github.com/vlang/v' 16 + 14 17 // The instance's name, used for the page titles and on the homepage. 15 18 name = 'beep' 16 19 // The welcome message to show on the homepage. ··· 31 34 32 35 // Toggle to allow any non-logged-in user to view data (posts, users, etc) 33 36 public_data = false 37 + 38 + // Owner's username. This is linked on the about page. Leave empty to disable. 39 + owner_username = '' 34 40 } 35 41 36 42 http = {
+1 -1
readme
··· 41 41 (assumes you already have a database somewhere) 42 42 $ v install EmmaTheMartian.Maple 43 43 $ v -cflags "-O3 -flto" . 44 - $ ./beep config.real.maple 44 + $ ./beep 45 45 46 46 If `v install ...` fails then you can install Maple 47 47 manually:
+15
scripts/fetchbuildinfo.vsh
··· 1 + #!/usr/bin/env v 2 + 3 + import os 4 + import emmathemartian.maple 5 + 6 + commit_res := os.execute('git rev-parse HEAD') 7 + if commit_res.exit_code != 0 { 8 + eprintln('failed to fetch commit: ${commit_res.output}') 9 + exit(1) 10 + } 11 + commit := commit_res.output.trim_space() 12 + 13 + maple.save_file('buildinfo.maple', { 14 + 'commit': maple.ValueT(commit) 15 + })!
+15 -3
src/main.v
··· 57 57 fn main() { 58 58 mut stopwatch := util.Stopwatch.new() 59 59 60 - config := webapp.load_config_from(os.args[1]) 61 - mut app := &App{ config: config } 60 + mut app := &App{ 61 + config: if os.args.len > 1 { 62 + webapp.load_config_from(os.args[1]) 63 + } else if os.exists('config.real.maple') { 64 + webapp.load_config_from('config.real.maple') 65 + } else { 66 + panic('no config found nor specified!') 67 + } 68 + buildinfo: if os.exists('buildinfo.maple') { 69 + webapp.load_buildinfo_from('buildinfo.maple') 70 + } else { 71 + webapp.BuildInfo{} 72 + } 73 + } 62 74 63 75 // connect to database 64 76 util.time_it( ··· 96 108 // make the website config, if it does not exist 97 109 app.get_or_create_site_config() 98 110 99 - if config.dev_mode { 111 + if app.config.dev_mode { 100 112 println('\033[1;31mNOTE: YOU ARE IN DEV MODE\033[0m') 101 113 } 102 114
+16 -7
src/templates/about.html
··· 3 3 <h1>about this instance</h1> 4 4 5 5 <div> 6 + <p><strong>general:</strong></p> 6 7 <p>name: @{app.config.instance.name}</p> 7 - <p>version: @{app.config.instance.version} (commit: @{app.commit})</p> 8 - <p>built at @{app.built_at} (<span id="built_at">date n/a</span>)</p> 9 - <p>built using @{app.v_hash}</p> 10 - 11 - @if app.config.instance.source != '' 12 - <p>source: <a href="@{app.config.instance.source}">@{app.config.instance.source}</a></p> 8 + <p>version: @{app.config.instance.version}</p> 9 + <p>public: @{app.config.instance.public_data}</p> 10 + @if app.config.instance.owner_username != '' 11 + <p>owner: <a href="/user/@{app.config.instance.owner_username}">@{app.config.instance.owner_username}</a></p> 13 12 @end 14 13 15 14 <br> 16 - 15 + <p><strong>stats:</strong></p> 17 16 <p>users: @{app.get_user_count()}</p> 18 17 <p>posts: @{app.get_post_count()}</p> 18 + 19 + @if app.config.instance.source != '' 20 + <br> 21 + <p><strong>nerd info:</strong></p> 22 + <p>beep source: <a href="@{app.config.instance.source}">@{app.config.instance.source}</a></p> 23 + <p>beep commit: <code><a href="@{app.config.instance.source}/commit/@{app.buildinfo.commit}">@{app.buildinfo.commit}</a></code></p> 24 + <p>V source: <a href="@{app.config.instance.v_source}">@{app.config.instance.v_source}</a></p> 25 + <p>V commit: <code><a href="@{app.config.instance.v_source}/commit/@{app.v_hash}">@{app.v_hash}</a></code></p> 26 + <p>built at <span id="built_at">date n/a</span> (unix: <code>@{app.built_at}</code>)</p> 27 + @end 19 28 </div> 20 29 21 30 <script>
+1 -1
src/templates/partial/footer.html
··· 15 15 <a href="/about">about</a> 16 16 </p> 17 17 18 - <p>powered by <a href="https://tamgled.org/emmeline.girlkisser.top/beep">beep</a></p> 18 + <p>powered by <a href="https://tangled.org/emmeline.girlkisser.top/beep">beep</a></p> 19 19 </footer> 20 20 21 21 </body>
+4 -4
src/webapp/app.v
··· 11 11 veb.StaticHandler 12 12 DatabaseAccess 13 13 pub: 14 - config Config 15 - commit string = @VMODHASH 16 - built_at string = @BUILD_TIMESTAMP 17 - v_hash string = @VHASH 14 + config Config 15 + buildinfo BuildInfo 16 + built_at string = @BUILD_TIMESTAMP 17 + v_hash string = @VHASH 18 18 pub mut: 19 19 auth auth.Auth[pg.DB] 20 20 validators struct {
+18
src/webapp/config.v
··· 16 16 allow_changing_theme bool 17 17 version string 18 18 source string 19 + v_source string 19 20 invite_only bool 20 21 invite_code string 21 22 public_data bool 23 + owner_username string 22 24 } 23 25 http struct { 24 26 pub mut: ··· 88 90 config.instance.allow_changing_theme = loaded_instance.get('allow_changing_theme').to_bool() 89 91 config.instance.version = loaded_instance.get('version').to_str() 90 92 config.instance.source = loaded_instance.get('source').to_str() 93 + config.instance.v_source = loaded_instance.get('v_source').to_str() 91 94 config.instance.invite_only = loaded_instance.get('invite_only').to_bool() 92 95 config.instance.invite_code = loaded_instance.get('invite_code').to_str() 93 96 config.instance.public_data = loaded_instance.get('public_data').to_bool() 97 + config.instance.owner_username = loaded_instance.get('owner_username').to_str() 94 98 95 99 loaded_http := loaded.get('http') 96 100 config.http.port = loaded_http.get('port').to_int() ··· 139 143 140 144 return config 141 145 } 146 + 147 + pub struct BuildInfo { 148 + pub mut: 149 + commit string 150 + } 151 + 152 + pub fn load_buildinfo_from(file_path string) BuildInfo { 153 + loaded := maple.load_file(file_path) or { panic(err) } 154 + mut buildinfo := BuildInfo{} 155 + 156 + buildinfo.commit = loaded.get('commit').to_str() 157 + 158 + return buildinfo 159 + }
+7 -1
src/webapp/pages.v
··· 234 234 235 235 @['/about'] 236 236 fn (mut app App) about(mut ctx Context) veb.Result { 237 - user := app.whoami(mut ctx) or { User{} } 237 + user := app.whoami(mut ctx) or { 238 + if !app.config.instance.public_data { 239 + ctx.error('not logged in') 240 + return ctx.redirect('/login') 241 + } 242 + User{} 243 + } 238 244 ctx.title = '${app.config.instance.name} - about' 239 245 return $veb.html('../templates/about.html') 240 246 }