Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/ten-buses-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@everipedia/iq-utils": minor
---

Add sendTwitterApiRequest lib function
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ coverage

# API keys and secrets
.env
.env.local

# Dependency directory
node_modules
Expand Down
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm lint-staged
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
"lint:fix": "pnpm lint --apply",
"watch:build": "tsc -p tsconfig.json -w",
"test": "vitest",
"coverage": "vitest run --coverage"
"coverage": "vitest run --coverage",
"prepare": "husky"
},
"dependencies": {
"axios": "^1.7.7",
"oauth-1.0a": "^2.2.6",
"quick-lru": "^7.0.0",
"zod": "^3.23.8"
},
Expand All @@ -29,6 +31,7 @@
"@changesets/cli": "^2.24.0",
"@types/node": "^22.7.4",
"changeset": "^0.2.6",
"husky": "^9.1.7",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we introducing husky?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was getting a failed build because it was not catching some errors here. So I setup a pre-commit hook to help prevent future occurrences

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could add in another PR. 👍 Keeps the PR lean

"lint-staged": "^15.2.10",
"tsup": "^8.3.0",
"typescript": "^4.7.4",
Expand Down
18 changes: 18 additions & 0 deletions pnpm-lock.yaml

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

1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from "./lib/wiki-score";
export * from "./lib/check-deep-equal";
export * from "./lib/check-wiki-validity";
export * from "./lib/twitter-api-client";
export * from "./data/constants";
export * from "./schema";
72 changes: 72 additions & 0 deletions src/lib/twitter-api-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import crypto from "node:crypto";
import OAuth from "oauth-1.0a";

type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";

interface IDiscordLogger {
log(data: DiscordLogData): Promise<void>;
}

type DiscordLogData = {
message: string;
title?: string;
color?: number;
};

export const oauth = new OAuth({
consumer: {
key: process.env.TWITTER_CONSUMER_KEY ?? "",
secret: process.env.TWITTER_CONSUMER_SECRET ?? "",
},
signature_method: "HMAC-SHA1",
hash_function: (base_string, key) => {
return crypto.createHmac("sha1", key).update(base_string).digest("base64");
},
});

const twitterAuthConfig = {
key: process.env.TWITTER_ACCESS_TOKEN ?? "",
secret: process.env.TWITTER_ACCESS_TOKEN_SECRET ?? "",
};

export async function sendTwitterApiRequest(
url: string,
method: HttpMethod,
logger?: IDiscordLogger,
body?: string,
): Promise<Response> {
if (!url.startsWith("https://api.twitter.com/")) {
throw new Error("Invalid Twitter API URL");
}
const oauth_headers = oauth.toHeader(
oauth.authorize(
{
url,
method,
},
twitterAuthConfig,
),
);

const response = await fetch(url, {
method,
headers: {
...oauth_headers,
"Content-Type": "application/json",
},
body,
});

if (!response.ok) {
const errorBody = await response.text();
logger?.log({
message: `🚨 HTTP error! status: ${response.status} ${response.statusText}. Body: ${errorBody}`,
title: "Twitter Authentication: makeAuthenticatedRequest",
});
throw new Error(
`HTTP error! status: ${response.status} ${response.statusText}. Body: ${errorBody}`,
);
}

return response;
}
14 changes: 9 additions & 5 deletions src/lib/wiki-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
MediaType,
type MetaData,
Tag,
Wiki,
} from "../schema";

// ===============================
Expand Down Expand Up @@ -103,12 +104,15 @@ export function isMediaContentAndCountValid(media: Media[]): boolean {
// ===============================
// Wiki-specific validation helpers
// ===============================
export function isEventWikiValid(wiki: any): boolean {
if (wiki.tags.some((tag: any) => tag.id === "Events")) {
export function isEventWikiValid(wiki: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why these changes? Are they related to this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got a failed build due to any usage

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird

tags: { id: string }[];
metadata: { id: string; value: string }[];
events: unknown[];
}): boolean {
if (wiki.tags.some((tag) => tag.id === "Events")) {
const referencesData =
wiki.metadata.find(
(meta: any) => meta.id === CommonMetaIds.Enum.references,
)?.value || "[]";
wiki.metadata.find((meta) => meta.id === CommonMetaIds.Enum.references)
?.value || "[]";
const references: { description: string }[] = JSON.parse(
referencesData,
) as { description: string }[];
Expand Down
Loading