Go implementation of pdsadmin cli

feat: add createInviteCode command

+101
+99
pdsadmin/cmd/createInviteCode.go
··· 1 + /* 2 + Copyright © 2025 QuietEngineer <qtengineer@proton.me> 3 + 4 + Permission is hereby granted, free of charge, to any person obtaining a copy 5 + of this software and associated documentation files (the "Software"), to deal 6 + in the Software without restriction, including without limitation the rights 7 + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 + copies of the Software, and to permit persons to whom the Software is 9 + furnished to do so, subject to the following conditions: 10 + 11 + The above copyright notice and this permission notice shall be included in 12 + all copies or substantial portions of the Software. 13 + 14 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 + THE SOFTWARE. 21 + */ 22 + package cmd 23 + 24 + import ( 25 + "bytes" 26 + "encoding/json" 27 + "fmt" 28 + "io" 29 + "net/http" 30 + "os" 31 + 32 + "github.com/spf13/cobra" 33 + "github.com/spf13/viper" 34 + ) 35 + 36 + type ServerCreateInviteCode_Input struct { 37 + UseCount int `json:"useCount"` 38 + } 39 + 40 + type ServerCreateInviteCode_Output struct { 41 + Code string `json:"code"` 42 + } 43 + 44 + var number *int 45 + 46 + // createInviteCodeCmd represents the createInviteCode command 47 + var createInviteCodeCmd = &cobra.Command{ 48 + Use: "createInviteCode", 49 + Short: "Create a new invite code", 50 + Example: "pdsadmin createInviteCode", 51 + Args: cobra.NoArgs, 52 + Run: func(cmd *cobra.Command, args []string) { 53 + if *number < 1 { 54 + fmt.Println("number must be >=1") 55 + os.Exit(1) 56 + } 57 + body := ServerCreateInviteCode_Input{ 58 + UseCount: *number, 59 + } 60 + jsonBody, err := json.Marshal(body) 61 + if err != nil { 62 + fmt.Printf("could not create json body: %s\n", err) 63 + os.Exit(1) 64 + } 65 + bodyReader := bytes.NewReader(jsonBody) 66 + 67 + req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("https://%s/xrpc/com.atproto.server.createInviteCode", viper.GetString("hostname")), bodyReader) 68 + if err != nil { 69 + fmt.Printf("could not create request: %s\n", err) 70 + os.Exit(1) 71 + } 72 + req.Header.Add("Content-Type", "application/json") 73 + req.SetBasicAuth("admin", viper.GetString("admin_password")) 74 + 75 + client := &http.Client{} 76 + res, err := client.Do(req) 77 + if err != nil { 78 + fmt.Printf("error making http request: %s\n", err) 79 + os.Exit(1) 80 + } 81 + resBody, err := io.ReadAll(res.Body) 82 + if err != nil { 83 + fmt.Printf("could not read response body: %s\n", err) 84 + os.Exit(1) 85 + } 86 + 87 + var inviteCode ServerCreateInviteCode_Output 88 + if err := json.Unmarshal(resBody, &inviteCode); err != nil { 89 + fmt.Printf("could not get invite code: %s\n", err) 90 + os.Exit(1) 91 + } 92 + fmt.Println(inviteCode.Code) 93 + }, 94 + } 95 + 96 + func init() { 97 + rootCmd.AddCommand(createInviteCodeCmd) 98 + number = createInviteCodeCmd.Flags().IntP("number", "n", 1, "number of times the code can be used") 99 + }
+2
pdsadmin/sample.config.yaml
··· 1 + admin_password: a_secure_password 2 + hostname: pds.example.com # without protocol (https) or path