Skip to content

Commit

Permalink
Merge branch 'main' into million-js
Browse files Browse the repository at this point in the history
  • Loading branch information
ethndotsh authored Mar 1, 2024
2 parents f7926f2 + 671fe2d commit 568ba12
Show file tree
Hide file tree
Showing 41 changed files with 841 additions and 341 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Openbin Contributors
Copyright (c) 2023 Unnamed Engineering

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
52 changes: 48 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
# openbin
[LW8 Hackathon] Pastebin clone that takes notes & code sharing to the next level.
# Openbin

Openbin is a Pastebin clone that takes notes & code sharing to the next level, by taking advantage of both a CLI and a web editor. We built it for the 8th Supabase Launch Week hackathon, attempting to solve issues we face often while trying to share snippets and code with friends and colleagues. The app is built using Go for the CLI and Next.js, Tailwind, TypeScript and `shadcn/ui` for the web editor. We take advantage of a whole lot of Supabase products, including the Database, Auth, Storage and the brand new Resend email integration.

# Documentation
The documentation is designed to help or refer you to the Openbin CLI. Occasionally, errors may occur, you may encounter bugs, or you simply have questions or need assistance in using it - if you are in one of these situations, [simply open an issue on the repo](https://github.com/ethndotsh/openbin/issues/new)!

To view the complete list of options not mentioned in the documentation: `openbin up --help`.

## Installation
Without guessing, this is the most important step in using CLI. You can install it on any operating system, whether Windows, Linux or macOS.

### Windows
### Windows (Powershell)
```powershell
irm https://openbin.dev/install.ps1 | iex
```
Expand All @@ -15,4 +20,43 @@ irm https://openbin.dev/install.ps1 | iex
curl -fsSL https://openbin.dev/install.sh | sh
```

Once you've installed Openbin on your machine, you'll be ready to begin your adventure with the CLI. 🎉
To make sure that Openbin is installed, enter `openbin --version` in your terminal. If it gives you the version, this means that Openbin has been successfully installed and you're ready to start using it! 🎉

## Login to your account
To get your pastes into your account, you should login to your Openbin account by entering this command:
```
openbin login
```
or with OAuth providers:
```
openbin login -p github/gitlab/bitbucket
```

Also, if you want to logout of your account, all you have to do is `openbin logout` - it's that simple!
> Please note that you can't upload without being logged in, so this step is necessary.
## Upload a file to Openbin

```
openbin upload [file.extension]
```
### Options:
`--title [value]`\
`--description [value]`\
`--language [value]`\
`--expire [value]`\
`--editor [value]`\
`--draft`

## Manage your pastes
The CLI lets you do everything just like with the web editor, and that means you can manage your pastes too!

### Get a list of the pastes you've created
```
openbin pastes
```
### Delete a paste
```
openbin delete [uuid]
```
> The UUID is located directly after the pastes/.
12 changes: 6 additions & 6 deletions cli/cmd/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ import (
var LoginCommand = cli.Command{
Name: "login",
Aliases: []string{"auth", "signin"},
Usage: "Login to your OpenBin account.",
Usage: "Login to your Openbin account.",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "email",
Aliases: []string{"e"},
Usage: "Your OpenBin account email.",
Usage: "Your Openbin account email.",
Required: false,
},
&cli.StringFlag{
Name: "provider",
Aliases: []string{"p"},
Usage: "Your OpenBin account provider.",
Usage: "Your Openbin account provider.",
Required: false,
DefaultText: "github",
},
Expand Down Expand Up @@ -78,8 +78,8 @@ var LoginCommand = cli.Command{
http.HandleFunc("/auth-callback", func(w http.ResponseWriter, r *http.Request) {
// get the code
code := r.URL.Query().Get("code")
fmt.Printf("Code: %s\n", code)
fmt.Printf("Code verifier: %s\n", codeVerifier)
// fmt.Printf("Code: %s\n", code)
// fmt.Printf("Code verifier: %s\n", codeVerifier)
// get the token
token, err := supabase.Auth.ExchangeCode(ctx, sb.ExchangeCodeOpts{
AuthCode: code,
Expand Down Expand Up @@ -126,7 +126,7 @@ var LoginCommand = cli.Command{
var LogoutCommand = cli.Command{
Name: "logout",
Aliases: []string{"signout"},
Usage: "Logout from your OpenBin account.",
Usage: "Logout from your Openbin account.",
Action: func(cCtx *cli.Context) error {
settings.SetAccessToken("")
settings.SetRefreshToken("")
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var DeleteCommand = cli.Command{
user, err := supabase.Auth.User(ctx, settings.AccessToken)

if err != nil {
cli.Exit("Could not get the user. Try signing in with `openbin login`.", 1)
cli.Exit("You don't seem to be signed in. Try running `openbin login` to sign in.", 1)
return err
}

Expand Down
4 changes: 2 additions & 2 deletions cli/cmd/pastes.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ var PastesCommand = cli.Command{
user, err := supabase.Auth.User(ctx, settings.AccessToken)

if err != nil {
cli.Exit("Could not get the user. Try signing in with `openbin login`.", 1)
cli.Exit("You don't seem to be signed in. Try running `openbin login` to sign in.", 1)
}

if user == nil {
cli.Exit("Could not get the user. Try signing in with `openbin login`.", 1)
cli.Exit("You don't seem to be signed in. Try running `openbin login` to sign in.", 1)
}

supabase.DB.AddHeader("Authorization", fmt.Sprintf("Bearer %s", settings.AccessToken))
Expand Down
27 changes: 24 additions & 3 deletions cli/cmd/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ type UploadOptions struct {

var UploadCommand = cli.Command{
Name: "upload",
Aliases: []string{"u"},
Usage: "Upload a file to OpenBin.",
Aliases: []string{"u", "up"},
Usage: "Upload a file to Openbin.",
ArgsUsage: "[FILE]",
Flags: []cli.Flag{
&cli.StringFlag{
Expand Down Expand Up @@ -91,6 +91,16 @@ var UploadCommand = cli.Command{
},
},
Action: func(cCtx *cli.Context) error {
user, err := supabase.Auth.User(ctx, settings.AccessToken)

if err != nil {
cli.Exit("You don't seem to be signed in. Try running `openbin login` to sign in.", 1)
}

if user == nil {
cli.Exit("You don't seem to be signed in. Try running `openbin login` to sign in.", 1)
}

args := UploadOptions{
File: cCtx.Args().First(),
Editor: cCtx.String("editor"),
Expand All @@ -104,6 +114,13 @@ var UploadCommand = cli.Command{
Quiet: cCtx.Bool("quiet"),
}

if args.File != "" {
// Check if the file exists
if _, err := os.Stat(args.File); os.IsNotExist(err) {
return cli.Exit("The file you specified does not exist.", 1)
}
}

if args.Language == "" {
// Try to get the language from the file extension
if args.File != "" {
Expand Down Expand Up @@ -226,7 +243,11 @@ func UploadFile(path string, opts UploadOptions) {
user, err := supabase.Auth.User(ctx, settings.AccessToken)

if err != nil {
cli.Exit("Could not get the user. Try signing in with `openbin login`.", 1)
cli.Exit("You don't seem to be signed in. Try running `openbin login` to sign in.", 1)
}

if user == nil {
cli.Exit("You don't seem to be signed in. Try running `openbin login` to sign in.", 1)
}

supabase.DB.AddHeader("Authorization", fmt.Sprintf("Bearer %s", settings.AccessToken))
Expand Down
4 changes: 2 additions & 2 deletions cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/urfave/cli/v2"
)

const VERSION = "1.0.5"
const VERSION = "1.0.8"

type GitHubResponse struct {
TagName string `json:"tag_name"`
Expand All @@ -24,7 +24,7 @@ func Run() {
Name: "openbin",
HelpName: "openbin",
EnableBashCompletion: true,
Description: "A CLI tool for OpenBin, a free and open-source pastebin alternative.",
Description: "A CLI tool for Openbin, a free and open-source pastebin alternative built primarily for command-line warriors.",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "version",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "openbin",
"version": "1.0.5",
"version": "1.0.7",
"description": "Pastebin clone that takes notes & code sharing to the next level.",
"scripts": {
"install": "go install github.com/ethndotsh/openbin@latest",
Expand Down
5 changes: 5 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions web/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ const nextConfig = {
images: {
domains: ["avatars.githubusercontent.com", "api.dicebear.com"],
},
async redirects() {
return [];
},
};

const millionConfig = {
Expand Down
18 changes: 1 addition & 17 deletions web/src/app/auth/callback/[redirect]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,5 @@ export async function GET(
);
}

const {
data: { session },
error: sessionError,
} = await supabase.auth.getSession();

if (sessionError) {
console.error("Error:", sessionError);
return;
}

if (!session) {
return;
}

return NextResponse.redirect(
new URL(`/profiles/${session.user.id}`, req.url),
);
return NextResponse.redirect(new URL(`/`, req.url));
}
18 changes: 1 addition & 17 deletions web/src/app/auth/callback/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,5 @@ export async function GET(req: NextRequest) {
await supabase.auth.exchangeCodeForSession(code);
}

const {
data: { session },
error: sessionError,
} = await supabase.auth.getSession();

if (sessionError) {
console.error("Error:", sessionError);
return;
}

if (!session) {
return;
}

return NextResponse.redirect(
new URL(`/profiles/${session.user.id}`, req.url),
);
return NextResponse.redirect(new URL(`/`, req.url));
}
15 changes: 7 additions & 8 deletions web/src/app/auth/delete/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,18 @@ export default async function DeletePage() {
<div className="flex-1 ">
<div className="flex h-full flex-col items-center justify-center space-y-4">
<h1 className="text-4xl font-bold">Delete Account</h1>
<p className="text-lg font-medium">
<p className="font-medium text-neutral-700">
Are you sure you want to delete your account?
</p>
<p className="text-lg font-medium">
<p className="max-w-xl text-center font-medium text-neutral-700">
This action is irreversible. All of your pastes will be deleted.
Remixed pastes made by other users will be unaffected.
</p>
<div className="flex w-full max-w-xl flex-row gap-2 rounded-xl border p-2">
<Link
href={`/profiles/${session?.user.id}`}
className={cn(buttonVariants({ variant: "default" }), "w-full")}
>
Cancel
<div className="flex w-full max-w-lg flex-col gap-2 p-2">
<Link href={`/profiles/${session?.user.id}`}>
<Button variant="outline" className="w-full">
Cancel
</Button>
</Link>
<form
action="/auth/delete/confirm"
Expand Down
9 changes: 9 additions & 0 deletions web/src/app/editor/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { LoadingSpinner } from "@/components/loading-spinner";

export default function Loading() {
return (
<div className="flex h-[90vh] w-screen items-center justify-center">
<LoadingSpinner />
</div>
);
}
14 changes: 7 additions & 7 deletions web/src/app/editor/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,27 @@ export default async function Page({
const profile = await getProfile(session?.user.id);
const supabase = createServerComponentClient();

let remixData: Paste | undefined;
let remixContent: string | undefined;
let remixData: Paste | undefined;

if (searchParams.remix) {
const { data: rD, error: remixError } = await supabase
const { data, error } = await supabase
.from("pastes")
.select("*, author(*)")
.eq("id", searchParams.remix)
.single();

if (!rD) {
if (!data) {
throw new Error("Remix not found");
}

if (remixError) {
throw new Error(remixError);
if (error) {
throw new Error(error);
}

const { data: fileData, error: fileError } = await supabase.storage
.from("pastes")
.download(rD.file);
.download(data.file);

if (fileError) {
throw new Error(fileError.message);
Expand All @@ -49,8 +49,8 @@ export default async function Page({

const file = await fileData.text();

remixData = rD;
remixContent = file;
remixData = data;
}

return (
Expand Down
Loading

0 comments on commit 568ba12

Please sign in to comment.