Я пытаюсь написать невероятно простое консольное приложение на C#, которое просто опубликует один твит в моем Твиттере от моего имени.
У меня есть учетная запись разработчика, и я прочитал ссылку, включая части, которые не имеют смысла и те, которые противоречат сами себе, я просмотрел старые вопросы и форумы в Твиттере, и что бы я ни пытался, я никогда не смогу пройти аутентификацию.
Моя цель - НЕ перенаправляться в веб-браузер для входа в мою учетную запись вручную, а использовать ключи и секреты учетной записи разработчика для аутентификации.
Я пробовал все следующее:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter the Tweet ID: ");
string tweetID = Console.ReadLine(); // no error checking here!
// convenient to load keys and tokens from a config file for testing
// edit .env.sample (and rename to .env) to add your keys and tokens (no quotation marks)
DotNetEnv.Env.Load();
string CONSUMER_KEY = "";
string CONSUMER_TOKEN = "";
string ACCESS_TOKEN = "";
string ACCESS_TOKEN_SECRET = "";
// this is the endpoint we will be calling
StringBuilder apiPath = new StringBuilder("https://api.twitter.com");
apiPath.Append("/2/tweets");
apiPath.AppendFormat("?ids={0}", tweetID);
apiPath.Append("&tweet.fields=attachments,author_id,context_annotations,created_at,entities,geo,id,in_reply_to_user_id,lang,possibly_sensitive,public_metrics,referenced_tweets,source,text,withheld");
apiPath.Append("&media.fields=duration_ms,height,media_key,preview_image_url,type,url,width");
apiPath.Append("&expansions=attachments.poll_ids,attachments.media_keys,author_id,geo.place_id,in_reply_to_user_id,referenced_tweets.id");
apiPath.Append("&poll.fields=duration_minutes,end_datetime,id,options,voting_status");
apiPath.Append("&place.fields=contained_within,country,country_code,full_name,geo,id,name,place_type");
apiPath.Append("&user.fields=created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,withheld");
string REQUEST_URL = apiPath.ToString();
// if you would like to compare to v1.1 then this alternative REQUEST_URL does that for Tweet ID 20
// string REQUEST_URL = "https://api.twitter.com/labs/2/tweets/20?tweet.fields=author_id,created_at,entities,source,public_metrics,lang,geo&expansions=author_id&user.fields=created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,url,username,verified,public_metrics";
// Create a new connection to the OAuth server, with a helper method
OAuthRequest client = OAuthRequest.ForProtectedResource("GET", CONSUMER_KEY, CONSUMER_TOKEN, ACCESS_TOKEN, ACCESS_TOKEN_SECRET);
client.RequestUrl = REQUEST_URL;
// add HTTP header authorization
string auth = client.GetAuthorizationHeader();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(client.RequestUrl);
request.Headers.Add("Authorization", auth);
Console.WriteLine("\nCalling " + REQUEST_URL + "\n");
// make the call and print the string value of the response JSON
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string strResponse = reader.ReadToEnd();
Console.WriteLine(strResponse); // we have a string (JSON)
}
}
// Source - https://stackoverflow.com/a/79676911
// Posted by Himanshu Kumar Sinha
// Retrieved 2025-12-01, License - CC BY-SA 4.0
public async Task ReplyToTweet(string replyText)
{
if (string.IsNullOrWhiteSpace(replyText))
{
return "Reply text cannot be empty.";
}
var ConsumerKey = "";
var ConsumerSecret = "";
var Token = "";
var TokenSecret = "";
var oAuth1 = OAuth1Authenticator.ForAccessToken(
consumerKey: ConsumerKey,
consumerSecret: ConsumerSecret,
token: Token,
tokenSecret: TokenSecret,
OAuthSignatureMethod.HmacSha256);
var options = new RestClientOptions("https://api.x.com")
{
Authenticator = oAuth1
};
var client = new RestClient(options);
var request = new RestRequest("2/tweets", Method.Post);
request.AddHeader("Content-Type", "application/json");
// Creating the body
var bodyObject = new
{
text = replyText
};
string body = JsonConvert.SerializeObject(bodyObject);
request.AddParameter("application/json", body, ParameterType.RequestBody);
var response = await client.ExecuteAsync(request);
if (response.IsSuccessful)
{
var responseData = JsonConvert.DeserializeObject(response.Content);
return $"tweet created successfully! Tweet ID: {responseData.data.id}";
}
else
{
return $"Failed to create reply tweet. Error: {response.ErrorMessage}\nResponse: {response.Content}";
}
}
Ничто из этого не работает. Я всегда получаю сообщение «Не авторизовано»/«Не удалось пройти аутентификацию».
Я на пределе возможностей и буду признателен за любую помощь в том, как просто опубликовать простой твит в моем твиттере, используя мою учетную запись, используя любые ключи и секреты, к которым у меня есть доступ в моей учетной записи разработчика без аутентификации в браузере.
Я пытаюсь написать невероятно простое консольное приложение на C#, которое просто опубликует один твит в моем Твиттере от моего имени. У меня есть учетная запись разработчика, и я прочитал ссылку, включая части, которые не имеют смысла и те, которые противоречат сами себе, я просмотрел старые вопросы и форумы в Твиттере, и что бы я ни пытался, я никогда не смогу пройти аутентификацию. Моя цель - НЕ перенаправляться в веб-браузер для входа в мою учетную запись вручную, а использовать ключи и секреты учетной записи разработчика для аутентификации. Я пробовал все следующее: [code]static async Task Main() { var consumerKey = ""; var consumerSecret = ""; var accessToken = ""; var accessTokenSecret = "";
var tweetText = "test";
var oauthNonce = Convert.ToBase64String(Encoding.ASCII.GetBytes(DateTime.Now.Ticks.ToString())); var oauthTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
var url = "https://api.twitter.com/1.1/statuses/update.json";
public static async Task ReplyToTweet(string replyText) { if (string.IsNullOrWhiteSpace(replyText)) { return "Reply text cannot be empty."; }
var ConsumerKey = CONSUMER_KEY; // also tried with API_KEY var ConsumerSecret = CONSUMER_SECRET; // also tried with API_SECRET var Token = ACCESS_TOKEN; var TokenSecret = ACCESS_TOKEN_SECRET;
var options = new RestClientOptions("https://api.x.com") { Authenticator = oAuth1 };
var client = new RestClient(options); var request = new RestRequest("2/tweets", Method.Post); request.AddHeader("Content-Type", "application/json");
// Creating the body var bodyObject = new { text = replyText };
string body = JsonSerializer.Serialize(bodyObject); request.AddParameter("application/json", body, ParameterType.RequestBody);
var response = await client.ExecuteAsync(request);
if (response.IsSuccessful) { var responseData = JsonSerializer.Deserialize(response.Content); return $"tweet created successfully! Tweet ID: {responseData.data.id}"; } else { return $"Failed to create reply tweet. Error: {response.ErrorMessage}\nResponse: {response.Content}"; } } [/code] . [code]class Program { static void Main(string[] args) {
Console.WriteLine("Enter the Tweet ID: "); string tweetID = Console.ReadLine(); // no error checking here!
// convenient to load keys and tokens from a config file for testing // edit .env.sample (and rename to .env) to add your keys and tokens (no quotation marks) DotNetEnv.Env.Load();
// this is the endpoint we will be calling StringBuilder apiPath = new StringBuilder("https://api.twitter.com"); apiPath.Append("/2/tweets"); apiPath.AppendFormat("?ids={0}", tweetID); apiPath.Append("&tweet.fields=attachments,author_id,context_annotations,created_at,entities,geo,id,in_reply_to_user_id,lang,possibly_sensitive,public_metrics,referenced_tweets,source,text,withheld"); apiPath.Append("&media.fields=duration_ms,height,media_key,preview_image_url,type,url,width"); apiPath.Append("&expansions=attachments.poll_ids,attachments.media_keys,author_id,geo.place_id,in_reply_to_user_id,referenced_tweets.id"); apiPath.Append("&poll.fields=duration_minutes,end_datetime,id,options,voting_status"); apiPath.Append("&place.fields=contained_within,country,country_code,full_name,geo,id,name,place_type"); apiPath.Append("&user.fields=created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,withheld"); string REQUEST_URL = apiPath.ToString();
// if you would like to compare to v1.1 then this alternative REQUEST_URL does that for Tweet ID 20 // string REQUEST_URL = "https://api.twitter.com/labs/2/tweets/20?tweet.fields=author_id,created_at,entities,source,public_metrics,lang,geo&expansions=author_id&user.fields=created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,url,username,verified,public_metrics";
// Create a new connection to the OAuth server, with a helper method OAuthRequest client = OAuthRequest.ForProtectedResource("GET", CONSUMER_KEY, CONSUMER_TOKEN, ACCESS_TOKEN, ACCESS_TOKEN_SECRET); client.RequestUrl = REQUEST_URL;
// make the call and print the string value of the response JSON HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream dataStream = response.GetResponseStream(); StreamReader reader = new StreamReader(dataStream); string strResponse = reader.ReadToEnd();
Console.WriteLine(strResponse); // we have a string (JSON) } } [/code] . [code]// Source - https://stackoverflow.com/a/79676911 // Posted by Himanshu Kumar Sinha // Retrieved 2025-12-01, License - CC BY-SA 4.0
public async Task ReplyToTweet(string replyText) { if (string.IsNullOrWhiteSpace(replyText)) { return "Reply text cannot be empty."; }
var ConsumerKey = ""; var ConsumerSecret = ""; var Token = ""; var TokenSecret = "";
var options = new RestClientOptions("https://api.x.com") { Authenticator = oAuth1 };
var client = new RestClient(options); var request = new RestRequest("2/tweets", Method.Post); request.AddHeader("Content-Type", "application/json");
// Creating the body var bodyObject = new { text = replyText };
string body = JsonConvert.SerializeObject(bodyObject); request.AddParameter("application/json", body, ParameterType.RequestBody);
var response = await client.ExecuteAsync(request);
if (response.IsSuccessful) { var responseData = JsonConvert.DeserializeObject(response.Content); return $"tweet created successfully! Tweet ID: {responseData.data.id}"; } else { return $"Failed to create reply tweet. Error: {response.ErrorMessage}\nResponse: {response.Content}"; } } [/code] Ничто из этого не работает. Я всегда получаю сообщение «Не авторизовано»/«Не удалось пройти аутентификацию». Я на пределе возможностей и буду признателен за любую помощь в том, как просто опубликовать простой твит в моем твиттере, используя мою учетную запись, используя любые ключи и секреты, к которым у меня есть доступ в моей учетной записи разработчика без аутентификации в браузере.