<commit_before>--- Metatables used to create objects from the data returned by the Twitter API.
--
-- @module  luatwit.objects
-- @license MIT
local assert, io_open, pairs, type =
      assert, io.open, pairs, type
local util = require "luatwit.util"

local _M = {}

-- Creates a new type table.
local function new_type(subtypes)
    local self = {
        _subtypes = subtypes,
    }
    self.__index = self
    return self
end

--- Access token returned by `luatwit.api:confirm_login`.
-- It's the result of the user authorizing the app, and contains the keys necessary to make API calls.
_M.access_token = new_type()

--- Saves the content of an `access_token` object into a file.
-- The output file can be loaded with `luatwit.load_keys`.
--
-- @param filename  Name of the destination file.
-- @return          The `access_token` itself.
function _M.access_token:save(filename)
    local file, err = io_open(filename, "w")
    assert(file, err)
    for k, v in pairs(self) do
        if not k:match("^oauth") then
            k = "--" .. k
        end
        file:write(k, ' = "', v, '"\n');
    end
    file:close()
    return self
end

--- HTTP Headers returned by the API calls.
_M.headers = new_type()

--- Extracts the rate limit info from the HTTP headers.
--
-- @return          Table with rate limit values.
function _M.headers:get_rate_limit()
    return {
        remaining = self["x-rate-limit-remaining"],
        limit = self["x-rate-limit-limit"],
        reset = self["x-rate-limit-reset"],
    }
end

--- Error description returned by the API calls.
_M.error = new_type()

--- Returns the error message.
--
-- @return          Error string.
function _M.error:__tostring()
    return self.errors[1].message
end

--- Returns the numeric error code.
--
-- @return          Error code.
function _M.error:code()
    return self.errors[1].code
end

--- User object.
_M.user = new_type{ status = "tweet", entities = "entities" }

--- List of `user` objects.
_M.user_list = new_type("user")

--- Cursor of `user` objects.
_M.user_cursor = new_type{ users = "user_list" }

--- Loads the next page of an user cursored request.
--
-- @return          Next `user_cursor` page, or <tt>nil</tt> if the current page is the last.
function _M.user_cursor:next()
    if self.next_cursor == 0 then return nil end
    return self._source_method{ cursor = self.next_cursor_str }
end

--- Loads the previous page of an user cursored request.
--
-- @return          Previous `user_cursor` page, or <tt>nil</tt> if the current page is the first.
function _M.user_cursor:prev()
    if self.previous_cursor == 0 then return nil end
    return self._source_method{ cursor = self.previous_cursor_str }
end

--- Tweet object.
_M.tweet = new_type{ user = "user", entities = "entities", retweeted_status = "tweet" }

--- Sends a tweet as a reply to this tweet.
--
-- @param args      Extra arguments for the <tt>tweet</tt> API method.
--                  The reply must text is passed in the <tt>status</tt> field.
--                  If the <tt>_mention</tt> option is set, it will prepend the @screen_name to the reply text.
-- @return          A `tweet` object.
function _M.tweet:reply(args)
    assert(type(args) == "table" and args.status, "must provide reply text in 'status' argument")
    args.in_reply_to_status_id = self.id_str
    if args._mention then
        args.status = "@" .. self.user.screen_name .. " " .. args.status
    end
    return self._client:tweet(args)
end

--- Retweets this tweet.
--
-- @param args      Extra arguments for the <tt>retweet</tt> API method.
-- @return          A `tweet` object.
function _M.tweet:retweet(args)
    args = args or {}
    args.id = self.id_str
    return self._client:retweet(args)
end

--- Delete this tweet.
--
-- @param args      Extra arguments for the <tt>delete_tweet</tt> API method.
-- @return          A `tweet` object.
function _M.tweet:delete(args)
    args = args or {}
    args.id = self.id_str
    return self._client:delete_tweet(args)
end

--- Add this tweet to favorites.
--
-- @param args      Extra arguments for the <tt>set_favorite</tt> API method.
-- @return          A `tweet` object.
function _M.tweet:set_favorite(args)
    args = args or {}
    args.id = self.id_str
    return self._client:set_favorite(args)
end

--- Remove this tweet from favorites.
--
-- @param args      Extra arguments for the <tt>unset_favorite</tt> API method.
-- @return          A `tweet` object.
function _M.tweet:unset_favorite(args)
    args = args or {}
    args.id = self.id_str
    return self._client:unset_favorite(args)
end

--- Get a list of retweets of this tweet.
--
-- @param args      Extra arguments for the <tt>get_retweets</tt> API method.
-- @return          A `tweet_list` object.
function _M.tweet:get_retweets(args)
    args = args or {}
    args.id = self.id_str
    return self._client:get_retweets(args)
end

--- Get a list of user ids who retweeted this tweet.
--
-- @param args      Extra arguments for the <tt>get_retweeter_ids</tt> API method.
-- @return          An `userid_cursor` object.
function _M.tweet:get_retweeter_ids(args)
    args = args or {}
    args.id = self.id_str
    return self._client:get_retweeter_ids(args)
end

--- Generates an OEmbed object for this tweet.
--
-- @param args      Extra arguments for the <tt>oembed</tt> API method.
-- @return          An `oembed` object.
function _M.tweet:oembed(args)
    args = args or {}
    args.id = self.id_str
    return self._client:oembed(args)
end
<commit_msg>objects.tweet: Add method to get the replied tweet in conversation threads<commit_after>--- Metatables used to create objects from the data returned by the Twitter API.
--
-- @module  luatwit.objects
-- @license MIT
local assert, io_open, pairs, type =
      assert, io.open, pairs, type
local util = require "luatwit.util"
local json = require "cjson"

local _M = {}

-- Creates a new type table.
local function new_type(subtypes)
    local self = {
        _subtypes = subtypes,
    }
    self.__index = self
    return self
end

--- Access token returned by `luatwit.api:confirm_login`.
-- It's the result of the user authorizing the app, and contains the keys necessary to make API calls.
_M.access_token = new_type()

--- Saves the content of an `access_token` object into a file.
-- The output file can be loaded with `luatwit.load_keys`.
--
-- @param filename  Name of the destination file.
-- @return          The `access_token` itself.
function _M.access_token:save(filename)
    local file, err = io_open(filename, "w")
    assert(file, err)
    for k, v in pairs(self) do
        if not k:match("^oauth") then
            k = "--" .. k
        end
        file:write(k, ' = "', v, '"\n');
    end
    file:close()
    return self
end

--- HTTP Headers returned by the API calls.
_M.headers = new_type()

--- Extracts the rate limit info from the HTTP headers.
--
-- @return          Table with rate limit values.
function _M.headers:get_rate_limit()
    return {
        remaining = self["x-rate-limit-remaining"],
        limit = self["x-rate-limit-limit"],
        reset = self["x-rate-limit-reset"],
    }
end

--- Error description returned by the API calls.
_M.error = new_type()

--- Returns the error message.
--
-- @return          Error string.
function _M.error:__tostring()
    return self.errors[1].message
end

--- Returns the numeric error code.
--
-- @return          Error code.
function _M.error:code()
    return self.errors[1].code
end

--- User object.
_M.user = new_type{ status = "tweet", entities = "entities" }

--- List of `user` objects.
_M.user_list = new_type("user")

--- Cursor of `user` objects.
_M.user_cursor = new_type{ users = "user_list" }

--- Loads the next page of an user cursored request.
--
-- @return          Next `user_cursor` page, or <tt>nil</tt> if the current page is the last.
function _M.user_cursor:next()
    if self.next_cursor == 0 then return nil end
    return self._source_method{ cursor = self.next_cursor_str }
end

--- Loads the previous page of an user cursored request.
--
-- @return          Previous `user_cursor` page, or <tt>nil</tt> if the current page is the first.
function _M.user_cursor:prev()
    if self.previous_cursor == 0 then return nil end
    return self._source_method{ cursor = self.previous_cursor_str }
end

--- Tweet object.
_M.tweet = new_type{ user = "user", entities = "entities", retweeted_status = "tweet" }

--- Sends a tweet as a reply to this tweet.
--
-- @param args      Extra arguments for the <tt>tweet</tt> API method.
--                  The reply must text is passed in the <tt>status</tt> field.
--                  If the <tt>_mention</tt> option is set, it will prepend the @screen_name to the reply text.
-- @return          A `tweet` object.
function _M.tweet:reply(args)
    assert(type(args) == "table" and args.status, "must provide reply text in 'status' argument")
    args.in_reply_to_status_id = self.id_str
    if args._mention then
        args.status = "@" .. self.user.screen_name .. " " .. args.status
    end
    return self._client:tweet(args)
end

--- Retweets this tweet.
--
-- @param args      Extra arguments for the <tt>retweet</tt> API method.
-- @return          A `tweet` object.
function _M.tweet:retweet(args)
    args = args or {}
    args.id = self.id_str
    return self._client:retweet(args)
end

--- Delete this tweet.
--
-- @param args      Extra arguments for the <tt>delete_tweet</tt> API method.
-- @return          A `tweet` object.
function _M.tweet:delete(args)
    args = args or {}
    args.id = self.id_str
    return self._client:delete_tweet(args)
end

--- Add this tweet to favorites.
--
-- @param args      Extra arguments for the <tt>set_favorite</tt> API method.
-- @return          A `tweet` object.
function _M.tweet:set_favorite(args)
    args = args or {}
    args.id = self.id_str
    return self._client:set_favorite(args)
end

--- Remove this tweet from favorites.
--
-- @param args      Extra arguments for the <tt>unset_favorite</tt> API method.
-- @return          A `tweet` object.
function _M.tweet:unset_favorite(args)
    args = args or {}
    args.id = self.id_str
    return self._client:unset_favorite(args)
end

--- Get a list of retweets of this tweet.
--
-- @param args      Extra arguments for the <tt>get_retweets</tt> API method.
-- @return          A `tweet_list` object.
function _M.tweet:get_retweets(args)
    args = args or {}
    args.id = self.id_str
    return self._client:get_retweets(args)
end

--- Get a list of user ids who retweeted this tweet.
--
-- @param args      Extra arguments for the <tt>get_retweeter_ids</tt> API method.
-- @return          An `userid_cursor` object.
function _M.tweet:get_retweeter_ids(args)
    args = args or {}
    args.id = self.id_str
    return self._client:get_retweeter_ids(args)
end

--- Generates an OEmbed object for this tweet.
--
-- @param args      Extra arguments for the <tt>oembed</tt> API method.
-- @return          An `oembed` object.
function _M.tweet:oembed(args)
    args = args or {}
    args.id = self.id_str
    return self._client:oembed(args)
end

--- Get the next tweet in a conversation thread.
--
-- @param args      Extra arguments for the <tt>get_tweet</tt> API method.
-- @return          A `tweet` object, or <tt>nil</tt> if this tweet is the first in the reply chain.
function _M.tweet:get_next_in_thread(args)
    local reply_id = self.in_reply_to_status_id_str
    if reply_id == nil or reply_id == json.null then return nil end
    args = args or {}
    args.id = reply_id
    return self._client:get_tweet(args)
end

{'fraction_non_alphanumeric': 0.12041749331493143, 'fraction_numerical': 0.0006900715949279737, 'mean_word_length': 2.679466835925103, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1324102', 'n_tokens_mistral': 3779, 'n_tokens_neox': 3737, 'n_words': 1230}