Skip to content
This repository has been archived by the owner on Dec 16, 2024. It is now read-only.

Commit

Permalink
fix: embeds and upload without cookie
Browse files Browse the repository at this point in the history
Fixes embeds and uses http header when uploading
  • Loading branch information
TroyKomodo committed Oct 26, 2024
1 parent 80186ac commit 12f543b
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 41 deletions.
94 changes: 53 additions & 41 deletions server/main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package main

import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"os/signal"
"path"
Expand All @@ -17,7 +17,6 @@ import (

"github.com/valyala/fasthttp"
"github.com/valyala/fasttemplate"
"go.mongodb.org/mongo-driver/bson/primitive"
)

const MetaTags = `
Expand All @@ -28,6 +27,32 @@ const MetaTags = `
<link type="application/json+oembed" href="%s">
`

const GQLQuery = `
query GetEmote($id: ObjectID!) {
emote(id: $id) {
id
name
animated
created_at
host {
url
files {
frame_count
width
height
format
}
}
owner {
id
display_name
}
channels {
total
}
}
}`

type EmoteFile struct {
FrameCount int `json:"frame_count"`
Format string `json:"format"`
Expand All @@ -37,11 +62,15 @@ type EmoteFile struct {

type GQLEmoteResponse struct {
Data struct {
Emote struct {
Emote *struct {
ID string `json:"id"`
Name string `json:"name"`
Animated bool `json:"animated"`
CreatedAt time.Time `json:"created_at"`
Host ImageHost `json:"host"`
Host struct {
URL string `json:"url"`
Files []EmoteFile `json:"files"`
} `json:"host"`
Owner struct {
ID string `json:"id"`
DisplayName string `json:"display_name"`
Expand All @@ -53,11 +82,6 @@ type GQLEmoteResponse struct {
} `json:"data"`
}

type ImageHost struct {
URL string `json:"url"`
Files []EmoteFile `json:"files"`
}

type OEmbedData struct {
AuthorName string `json:"author_name"`
AuthorURL string `json:"author_url"`
Expand Down Expand Up @@ -110,44 +134,28 @@ func main() {
} else {
if strings.HasPrefix(pth, "/emotes/") {
id := strings.TrimSpace(strings.Split(strings.TrimPrefix(pth, "/emotes/"), "?")[0])
emoteID, err := primitive.ObjectIDFromHex(id)

// handle emote route
body, err := json.Marshal(map[string]any{
"query": GQLQuery,
"variables": map[string]string{
"id": id,
},
})

if err != nil {
log.Println("Failed to marshal request: ", err)
goto end
}

// handle emote route
query := url.Values{}
query.Set("query", fmt.Sprintf(`
{
emote(id: "%s") {
name
animated
created_at
host {
url
files {
frame_count
width
height
format
}
}
owner {
id
display_name
}
channels {
total
}
}
}`, emoteID.Hex()))

req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s?%s", gqlApiURL, query.Encode()), nil)
req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s", gqlApiURL), bytes.NewReader(body))
if err != nil {
log.Println("Failed to make request: ", err)
goto end
}

req.Header.Set("Cf-Connecting-Ip", string(ctx.Request.Header.Peek("Cf-Connecting-Ip")))

resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Println("Failed to do request: ", err)
Expand All @@ -161,15 +169,19 @@ func main() {
goto end
}

if resp.StatusCode != 200 {
log.Println("Failed to get emote: ", string(data))
goto end
}

gqlResp := GQLEmoteResponse{}
if err := json.Unmarshal(data, &gqlResp); err != nil {
log.Println("Failed to parse response: ", err)
goto end
}

emote := gqlResp.Data.Emote
if len(emote.Host.Files) == 0 {
log.Println("No files")
if emote == nil || len(emote.Host.Files) == 0 {
goto end
}

Expand All @@ -185,7 +197,7 @@ func main() {

oembed, _ := json.Marshal(OEmbedData{
AuthorName: fmt.Sprintf("%s by %s (%d Channels)", emote.Name, emote.Owner.DisplayName, emote.Channels.Total),
AuthorURL: fmt.Sprintf("%s/emotes/%s", websiteURL, emoteID.Hex()),
AuthorURL: fmt.Sprintf("%s/emotes/%s", websiteURL, emote.ID),
ProviderName: "7TV.APP - It's like a third party thing",
ProviderURL: websiteURL,
Type: "image",
Expand Down
6 changes: 6 additions & 0 deletions src/views/emote-upload/EmoteUpload.vue
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ import { Permissions } from "@/structures/Role";
import Checkbox from "@/components/form/Checkbox.vue";
import TextInput from "@/components/form/TextInput.vue";
import Icon from "@/components/utility/Icon.vue";
import { useStore } from "../../store/main";
const EmoteTagList = defineAsyncComponent(() => import("@/views/emote-upload/EmoteTagList.vue"));
Expand Down Expand Up @@ -234,6 +235,8 @@ const handleFile = async (file: File) => {
// Upload (network request)
const uploadProgress = ref(0);
const uploadError = ref("");
const store = useStore();
const upload = () => {
uploadError.value = "";
const data = {
Expand All @@ -252,6 +255,9 @@ const upload = () => {
req.setRequestHeader("X-Emote-Data", JSON.stringify(data));
req.setRequestHeader("Content-Type", mime);
req.setRequestHeader("Content-Length", buf.value.byteLength.toString(10));
if (store.authToken) {
req.setRequestHeader("Authorization", `Bearer ${store.authToken}`);
}
req.withCredentials = true;
req.upload.onprogress = (progress) => (uploadProgress.value = (progress.loaded / progress.total) * 100);
req.onload = () => {
Expand Down
7 changes: 7 additions & 0 deletions src/views/user/UserSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ import Icon from "@/components/utility/Icon.vue";
import UserEntitlementModal from "./UserEntitlementModal.vue";
import UserCosmeticsUpdateModal from "./UserSettingsCosmeticsUpdateModal.vue";
import UserProfileSettings from "./UserSettingsProfile.vue";
import { useStore } from "../../store/main";
import AnnotatedBadge from "../store/AnnotatedBadge.vue";
export interface FormType {
Expand Down Expand Up @@ -198,6 +199,8 @@ onCosmetics(async (res) => {
const uploading = ref(false);
const store = useStore();
const m = useMutationStore();
const submit = async () => {
if (!actor.user || uploading.value) {
Expand All @@ -213,6 +216,10 @@ const submit = async () => {
const req = new XMLHttpRequest();
req.open("PUT", `${import.meta.env.VITE_APP_API_REST as string}/users/${tgt}/profile-picture`, true);
req.setRequestHeader("Content-Length", form.profile_picture.byteLength.toString(10));
if (store.authToken) {
req.setRequestHeader("Authorization", `Bearer ${store.authToken}`);
}
req.withCredentials = true;
// req.upload.onprogress = (progress) => {}; // TODO: show upload progress
Expand Down

0 comments on commit 12f543b

Please sign in to comment.