絶滅

どうでもいい

全ツイート履歴から特定のツイートを抽出して API 叩いて削除するやつ

オギャー

全ツイート履歴をダウンロードする

全ツイート履歴をダウンロードします

/root/data/js/tweets/ にある .js ファイルの一行目を削除する

cpp

#define _CRT_SECURE_NO_WARNINGS
#include "bits/stdc++.h"
#include <filesystem>

using namespace std;

namespace fs = experimental::filesystem;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    string path_tweets = "/root/data/js/tweets/";
    
    for (auto ent : fs::recursive_directory_iterator(path_tweets)) {
        string path_file = ent.path().string();
        ifstream ifs(path_file);
        string header;
        getline(ifs, header); // skip header
        string data;
        string line;
        while (getline(ifs, line)) data += line + "\n";
        ifs.close();
        ofstream ofs(path_file);
        ofs << data << endl;
        ofs.close();
    }

    return 0;
}

Java + Jackson で特定の条件を満たすツイートを探す

java

import java.io.File;
 
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {

    public static void main(String[] args) throws Exception {
        int numTweets = 0, numTweetsWithURL = 0;
        
        String path = "/root/data/js/tweets";
        File dir = new File(path);
        File[] files = dir.listFiles();
        for(File file : files) {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode node = mapper.readTree(file);
            for(JsonNode tweet : node) {
                numTweets++;
                String text = tweet.get("text").toString();
                if(text.matches(".*https?://.*")) { 
                    // リンクを含むツイートのみカウント
                    numTweetsWithURL++;
                }
            }
        }
        
        System.out.println("TweetsWithURL: " + numTweetsWithURL + "/" + numTweets);
        // TweetsWithURL: 1376/6963
    }
}

動機としては猫画像以外のツイートを全部消したいので

google spreadsheet で tweets.csv を開いたときの列数と numTweets が一致することを確認

アクセストークンとかを得る

belltzel.dev

利用目的とかを英文で書かされるのでクソ面倒くさかった

Twitter4J でよしなに削除する

java

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.conf.ConfigurationBuilder;

public class Main {

    public static void main(String[] args) throws Exception {
        int numTweets = 0, numTweetsWithURL = 0;
        
        // ID collection part
        String path = "C:\\Users\\my316g\\Desktop\\766013394_fcd78b43f094dfa6bdac79806c379b8f0410ef552\\data\\js\\tweets";
        File dir = new File(path);
        File[] files = dir.listFiles();
        List<Long> id_strs = new ArrayList<Long>();
        for(File file : files) {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode node = mapper.readTree(file);
            for(JsonNode tweet : node) {
                numTweets++;
                String text = tweet.get("text").toString();
                String id_str = tweet.get("id_str").toString();
                if(text.matches(".*https?://.*")) { 
                    // リンクを含むツイートのみカウント
                    numTweetsWithURL++;
                }
                else {
                    id_strs.add(Long.parseLong(id_str.substring(1, id_str.length() - 1))); // remove quote
                }
            }
        }
        System.out.println("TweetsWithURL: " + numTweetsWithURL + "/" + numTweets);
        
        // API part
        ConfigurationBuilder cb = new ConfigurationBuilder();
        cb.setDebugEnabled(true)
            .setOAuthConsumerKey("*********************")
            .setOAuthConsumerSecret("******************************************")
            .setOAuthAccessToken("**************************************************")
            .setOAuthAccessTokenSecret("******************************************");
        TwitterFactory tf = new TwitterFactory(cb.build());
        
        Twitter twitter = tf.getInstance();
        if (!twitter.getAuthorization().isEnabled()) {
            System.out.println("OAuth consumer key/secret is not set.");
            System.exit(-1);
        }
        
        int destroyed = 0, total = 0;
        for(long id_str : id_strs) {
            try {
                Status status = twitter.destroyStatus(id_str);
                System.out.println("successfully destroyed the status: [" + status.getText() + "].");
                destroyed++;
            } catch (TwitterException te) {
                System.out.println("Failed to destroy status: " + te.getMessage());
            }
            total++;
            System.out.println(destroyed + "/" + total);
        }
    }
}

クリーンになったおれを令和でもよろしく