kumuのつぶやき

フロントエンド勉強中の学生のただつぶやき

go-twitterでusers/showとfavorites/listを叩く

goのTwitter API用ライブラリは、有名どころではanacondaとgo-twitterがある。
とりあえず今回はgo-twitterを使用する。


ちなみにusers/showはユーザーのプロフィールを取得するというもの。

developer.twitter.com


favorites/listはユーザーがお気に入りに登録したツイートの一覧を取得するエンドポイント。 developer.twitter.com


コード

consumerKeyなどはenvファイルに記述し、godotenvなど使うといいかも

初期設定↓
import(
    "github.com/dghubble/go-twitter/twitter"
    "github.com/dghubble/oauth1"
)
config := oauth1.NewConfig("consumerKey", "consumerSecret")
token := oauth1.NewToken("accessToken", "accessSecret")
httpClient := config.Client(oauth1.NoContext, token)

client := twitter.NewClient(httpClient)
users/show
user, res, err := client.Users.Show(&twitter.UserShowParams{
    ScreenName: id,
})

UserShowParamsにはUserID, ScreenName, IncludeEntitiesを指定できる。
UserIDはユーザごとに割り当てられている値。
ここで調べられる。idtwi | Twitter IDチェッカー(変更履歴の追跡)

よく見る@から始まるIDはScreenName

IncludeEntitiesは正直よくわからない。

UserID ScreenNameはどちらかは必須となっている。

取得したユーザ情報はこれ見るといいかも。
twitter package - github.com/dghubble/go-twitter/twitter - pkg.go.dev

favorites/list
tweets, res, err := client.Favorites.List(&twitter.FavoriteListParams{
    ScreenName: id,
    Count:      count,
})

FavoriteListParamsに指定できるもの↓
UserID
ScreenName
Count -> 検索する数。1~200
SinceID -> ツイートのID。そのツイートより後のツイートを取得
MaxID -> ツイートのID。そのツイートより前のツイートを取得
IncludeEntities -> 画像や動画の情報が含まれるかどうからしい。
TweetMode -> Twitter APIの方には無く、go-twitterにしかない。よくわからない。
UserID ScreenNameはどちらか必須。

取得したツイート情報はこれ見るといいかも。
twitter package - github.com/dghubble/go-twitter/twitter - pkg.go.dev

go runで"# command-line-arguments"

分割したファイル内の関数がundefinedになってる。
引数に指定したファイルのみコンパイルされるため、全て指定する。

- ...
  - main.go
  - a.go

a.go

...
func Run() {
  fmt.Printf("test")
}

main.go

...
func main() {
  Run()
}
// error
➜ go run main.go
# command-line-arguments
./main.go:13:9: undefined: Connect

解決法

go run main.go a.go or go run *.go

vite ✖️ React ✖️ TS メモ

普段npmしか使ってないのでnpmのみ
npm init vite@latest

➜ npm init vite@latest
Need to install the following packages:
  create-vite@latest
Ok to proceed? (y) y
✔ Project name: … 
✔ Package name: … 
✔ Select a framework: › react
✔ Select a variant: › react-ts
package.json
{...
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
...}

vscodeでTSのバージョンをワークスペースに合わせないとエディター側でエラーが出ることがある。

WebWorker(Offscreen)でCanvasを描画する

これの続き。
grekumu.hatenablog.jp

前回、WebWorker上でcanvas使うなら、OffscreenCanvas使おうって書いた。
ただ実際に試しては無かったので、試してみたよって話。

worker-loaderをインストール

前回いろいろやって、アンインストールしたworker-loaderを再インストールした。
config-overrides.js

config.module.rules.push({
  test: /\.worker\.js$/ ,
  use: { loader: 'worker-loader' }
});
import Worker from 'worker-loader!./wasm.worker';



CanvasをWebWorkerへ渡す

とりあえずコード
App.tsx

const canvas = document.getElementById('canvas') as HTMLCanvasElement;
const offscreen = canvas.transferControlToOffscreen();
worker.postMessage({ canvas: offscreen }, [offscreen]);

wasm.worker.ts

self.onmessage = (event: any)=> {
  const data = event.data;
  const canvas = data.canvas.getContext('webgl');
  // wasm側にCanvasを渡す
  call(canvas);
}

とりあえずこれで描画できるはず。


再描画しようとして詰まった


CanvasgetELementByIdで取得して、再描画しようとしたら出たエラー。
f:id:greKumu:20201211060834j:plain
InvalidStateError: Failed to execute 'transferControlToOffscreen' on 'HTMLCanvasElement': Cannot transfer control from a canvas for more than one time.

解決策

このサイトを参考にしたらできた。
newinweb.com

useRefでうまくできないし、いい案が思い浮かばず直接DOM操作してる。

// HTML
<div id="canvas-container"></div>
// TS
document.getElementById('canvas-container')!.innerHTML = '<canvas id="canvas"></canvas>'
canvas = document.getElementById('canvas')! as HTMLCanvasElement;



WebWorkerが複数作成される。

これは再描画する際にnew Worker()をしていた。
f:id:greKumu:20201211062412j:plain

解決策

新しく作成させない。
or
worker.terminate()を行う。


おわり

一応できた。

webworker内でwasmを使用しようとして失敗した(WebGL)

IPFactory Advent Calendar 2020 - Qiitaの8日目の記事

これの続き。
grekumu.hatenablog.jp


wasmの勉強で、こんな感じのやつGLSL Sandbox Gallery作ろうとしていて、wasmの処理をWebWorkerで行うつもりだったが、うまくできなかったって話。

WebWorker使おうと思った理由 www.sitepen.com

インストール

とりあえずworker-loaderをインストール。
npm install worker-loader --save-dev

config-overrides.jsに追加。

 config.module.rules.push({
    test: /\.worker\.js$/,
    use: { loader: 'worker-loader' }
 });

けどうまくいかない。

エラーや試したこと。


Uncaught SyntaxError: Unexpected token <

DevToolsで確認すると、WebWorkerがHTMLを返している。
あんまりWebWorker使ってこなかったから、構文が間違ってるか、loaderあたりだと思う。


グローバルオブジェクトの設定

webpackでHMRが有効だと、WebWorkerでwindow is not definedってなる話。
config-overrides.jsにグローバルオブジェクト設定してないせいかと思い、
config.output.globalObject = 'this';
と、設定した。


wasmのDynamic import

worker-loaderを使用し、WebWorker上からDynamic importするとエラーが出る。
これを見る限り、worker-loaderを使用しなければいいらしいので、とりあえず試してみた。
github.com


ReferenceError: Window is not defined.

Windowが大文字なのはlib.dom.d.tsを参照しているから?
んで、よく考えるとこれDOM参照しようとしてる。
てか、そもそもwasm側でweb-syscanvasを参照しており、結果的にWebWorker内でwindowオブジェクトを参照していた。(早く気付け俺。)


解決策 OffScreenCanvasを使う

今回の敗因はこれ。
描画はDOMに直接依存している。そのため、WebWorker上ではCanvasWebGLの描画ができない。(これ理解してなかった。)

OffscreenCanvasレンダリングはDOMから完全に切り離されているため、WebWorker上で描画ができるようになる。

developers.google.com

MDN見た感じsafariとかFirefoxが未対応。
これ使えば対応してないブラウザは色々置き換えてくれるらしい?
GitHub - ai/offscreen-canvas: Polyfill for OffscreenCanvas to move Three.js/WebGL/2D canvas to Web Worker



おわり

ただ失敗したよって話。
customize-craworker-pluginとか色々試したけどそもそも無理だった。
まだOffScreenCanvasを試してないから、まず試してみる。
アドカレ、他の人の記事と比べて内容ショボいとか言わないで。

Rust 文字列

文字列型

  1. String
  2. &str

// ヒープに割り当てる
let a = String::from("test");
let a = "test".to_string();
let a: String = "test".into();

// read only memory上に割り当てられた文字列への参照
let b: &'static str = "test";
// &str
let b = "test";


リテラル

// "test"
let byte_escape = "\x74\x65\x73\x74";
// [116, 101, 115, 116]
let byte_escape = b"\x74\x65\x73\x74";

// unicode "א"
let ucode = "\u{05D0}";

// raw string "\x74 \u{05D0}"
let raw_str = r"\x74 \u{05D0}";
// 引用符使う場合
let raw_str = r#" "test" "#;

// バイト文字列 [116, 101, 115, 116]
let a: &[u8; 4] = b"test";


Create React AppしたReactでWebAssemblyをインポートした

Webpackはwasmファイルの扱い方を知らないため、そのままwasmファイルをインポートすると、エラーが発生する。

コマンド
npm install --save-dev react-app-rewired wasm-loader

config-overrides.jsというファイルを作成し、下記を記述。

const path = require('path');

module.exports = function override(config, env) {
  const wasmExtensionRegExp = /\.wasm$/;

  config.resolve.extensions.push('.wasm');

  config.module.rules.forEach(rule => {
    (rule.oneOf || []).forEach(oneOf => {
      if (oneOf.loader && oneOf.loader.indexOf('file-loader') >= 0) {
        oneOf.exclude.push(wasmExtensionRegExp);
      }
    });
  });

  config.module.rules.push({
    test: wasmExtensionRegExp,
    include: path.resolve(__dirname, 'src'),
    use: [{ loader: require.resolve('wasm-loader'), options: {} }]
  });

  return config;
};


package.jsonを変更する。

"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
  "eject": "react-scripts eject"
},