threadsjs / threads.js

A Node.js library for the Threads API
MIT License
279 stars 29 forks source link

Client instatiated with token isn't working #64

Closed LilaRest closed 1 year ago

LilaRest commented 1 year ago

Steps to reproduce: 1) Run this piece of code once

import { Client } from "@threadsjs/threads.js";
import  fs from "fs";
import path from "path";

const tokenPath = path.join(__dirname, "token.json");

const saveToken = (token: string) => {
  fs.writeFileSync(tokenPath, JSON.stringify({ token }));
};

const restoreToken = () => {
  if (!fs.existsSync(tokenPath)) return null;
  const { token } = JSON.parse(fs.readFileSync(tokenPath, "utf-8"));
  return token as string;
};

const main = async () => {
  // Try loading token from disk
  const token = restoreToken();
  console.log(token)

  // Initialize the client and login
  let client: Client;

  // If token was cached, use it
  if (token !== null) client = new Client({ token });

  // Else, initiate a new login process
  else {
    client = new Client({});
    await client.login(
      "<username>",
      "<password>"
    );
    saveToken(client.token);
  }

  const following = await client.users.following(client.userId);
  console.log(following)
};

main();

2) Run it a second time so the client is initiated from the token cached to disk. This outputs the HTML of Instagram "Page not found" page

stevenlafl commented 1 year ago

Try running decodeURIComponent() on the token first before passing it in as a token.

LilaRest commented 1 year ago

Try running decodeURIComponent() on the token first before passing it in as a token.

Thanks for this suggestion, it appears to have no effect on the error :|

elijah-wright commented 1 year ago

what version are you using? I just tried this and it worked. Instagram pushed some updates this morning that changed auth

LilaRest commented 1 year ago

I'm using latest version 1.7.2. Weird thing

LilaRest commented 1 year ago

Oh yeah that makes sense. I'll be glad to test it once it's done :)

elijah-wright commented 1 year ago

ok, so I figured out what was actually going on. at first I thought it was the tokens but comparing the clients, the one that doesn't work doesn't have client.userId. the userId isn't generated when you use a token. give me a minute to figure out how to get that

elijah-wright commented 1 year ago

idk if there is a way to get it without logging in, which is what #32 was about. I'll keep this open in case anyone has any ideas. the issue is just with how you're using client.userId which doesn't exist unless you log in. if you provide another id, it'll work

stevenlafl commented 1 year ago

Well hold on a moment, I am using the token this exact way with 1.7.1. I don't have a problem, why is that?

elijah-wright commented 1 year ago

does client.userId exist on your client @stevenlafl?

LilaRest commented 1 year ago

Let me know if there anything I can do to help

stevenlafl commented 1 year ago

Oh, I'm storing it. Sorry. I suppose if you were to base64 encode a JSON string with the token AND the userid, meant specifically for this app, that would be sufficient.

base64(JSON.stringify({token, userId})) and then in the client implementation code grab it back out if that base64 encoded json (as our "token") is passed in. Our resulting tokens would only be compatible with this implementation, though. And maybe that's fine.

stevenlafl commented 1 year ago
import { Client } from "@threadsjs/threads.js";
import  fs from "fs";
import path from "path";

const tokenPath = path.join(__dirname, "token.json");

const saveToken = (token: string, userId: string) => {
  fs.writeFileSync(tokenPath, JSON.stringify({ token, userId }));
};

const restoreToken = () => {
  if (!fs.existsSync(tokenPath)) return null;
  return JSON.parse(fs.readFileSync(tokenPath, "utf-8"));;
};

const main = async () => {
  // Try loading token from disk
  const {token, userId} = restoreToken();
  console.log(token)

  // Initialize the client and login
  let client: Client;

  // If token was cached, use it
  if (token !== null) {
    client = new Client({ token });
    client.userId = userId;
  }

  // Else, initiate a new login process
  else {
    client = new Client({});
    await client.login(
      "<username>",
      "<password>"
    );
    saveToken(client.token, client.userId);
  }

  const following = await client.users.following(client.userId);
  console.log(following)
};

main();

Like this?

LilaRest commented 1 year ago

Thanks @stevenlafl ! But I tried and it doesn't work for me :/ But you talked about base64 and I can't see any usage of base64 in this demonstration

stevenlafl commented 1 year ago

They may need to delete their existing token.json

LilaRest commented 1 year ago

Works like a charm, thanks!

elijah-wright commented 1 year ago

alr, I'm closing this now