Skip to content

Feedback #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 85 commits into
base: feedback
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
32be9dd
Setting up GitHub Classroom Feedback
github-classroom[bot] Nov 14, 2022
90855f2
Update project description
mskwr Nov 14, 2022
284ed71
Change library to interact with Twitter API
mskwr Dec 16, 2022
3055f5f
Change library for Twitter API
mskwr Dec 17, 2022
3fd47ac
Add tokio to libraries
mskwr Jan 3, 2023
6d14517
Add authorization with Twitter
mskwr Jan 3, 2023
eb6afa1
Create simple bot
mskwr Jan 3, 2023
b0ad52a
Update README.md
mskwr Jan 3, 2023
40ff076
Beautify README.md
mskwr Jan 3, 2023
8962321
Add some useful utilities
mskwr Jan 5, 2023
6278c43
Update README.md
mskwr Jan 5, 2023
6505f72
Add utility to get user's latest tweet date
mskwr Jan 5, 2023
34f9d21
Merge remote-tracking branch 'origin/main'
mskwr Jan 5, 2023
e91910f
Count unique users whose tweets included given string
mskwr Jan 5, 2023
50940e7
Fix typo
mskwr Jan 5, 2023
499f0bd
Add link to Twitter account
mskwr Jan 5, 2023
739534c
Beatify README.md
mskwr Jan 5, 2023
a2b8a3f
Another attemp to beatify README.md
mskwr Jan 5, 2023
1d53a93
One more attemp to beautify README.md
mskwr Jan 5, 2023
9864c92
Beautify README.md
mskwr Jan 6, 2023
fe07263
Remove unnecessary tokio features
mskwr Jan 6, 2023
c9fbd7f
Change package name
mskwr Jan 6, 2023
bf282b0
Change the order of libraries
mskwr Jan 6, 2023
f75009b
Change project photo
mskwr Jan 6, 2023
f491559
Change project photo format
mskwr Jan 6, 2023
5c182f7
Fix formatting
mskwr Jan 6, 2023
872d57d
Correct typo
mskwr Jan 28, 2023
8ee3bd8
Add license
mskwr Jan 28, 2023
d1015f7
Update license infomation
mskwr Jan 28, 2023
73e58a3
Add reply generator
mskwr Jan 29, 2023
a762e9d
Add reply generator
mskwr Jan 29, 2023
f98e70d
Add rand library
mskwr Jan 29, 2023
2510cef
Add tweet generator
mskwr Jan 29, 2023
d0e1add
Apply cargo clippy --fix
mskwr Jan 29, 2023
4004b85
Merge remote-tracking branch 'origin/main'
mskwr Jan 29, 2023
514afab
Add handling of first ever stat on profile
mskwr Jan 29, 2023
c7cb53e
Improve converting Options
mskwr Jan 29, 2023
2d7bc22
Switch to iterators
mskwr Jan 29, 2023
6bdbe57
Remove useless const
mskwr Jan 29, 2023
c3cd290
Use map while looking through tweets
mskwr Jan 29, 2023
26a21ed
Use even more iterators
mskwr Jan 29, 2023
16eb636
Consider Option<Vector<Tweet>> = None as empty Vector
mskwr Jan 29, 2023
179a43d
Add ability to extract stats from text
mskwr Jan 29, 2023
296dc41
Add ability to extract stats from text
mskwr Jan 29, 2023
dc02a17
Update bot's core
mskwr Jan 29, 2023
c1455b3
Update bot's core
mskwr Jan 29, 2023
2aff3ec
Update README.md
mskwr Jan 29, 2023
aec598d
Add comment
mskwr Jan 29, 2023
6251173
Merge remote-tracking branch 'origin/main'
mskwr Jan 29, 2023
c586d22
Add ability to post daily stats
mskwr Jan 29, 2023
eb52257
Add utility to find recent replies
mskwr Jan 29, 2023
2390335
Add utility to find recent replies
mskwr Jan 29, 2023
81823a6
Add utility to find user's name by id
mskwr Jan 29, 2023
89c7b60
Add utility to find user's name by id
mskwr Jan 29, 2023
4800f57
Add utility to find user's name by id
mskwr Jan 29, 2023
a4eddef
Add utility to post replies
mskwr Jan 29, 2023
be5cdc8
Fully working version of bot
mskwr Jan 29, 2023
29974a4
Fully working version of bot
mskwr Jan 29, 2023
083bbbe
Add terminal messages
mskwr Jan 29, 2023
6c9b4da
Add colours
mskwr Jan 29, 2023
acdd0d1
Change date format of messages
mskwr Jan 29, 2023
507bbde
Apply cargo fmt changes
mskwr Jan 29, 2023
8ebfcc2
Improve bot's mistake detection
mskwr Jan 29, 2023
ac2f724
Improve bot's mistake detection
mskwr Jan 29, 2023
afd3019
Improve dates formatting
mskwr Jan 30, 2023
ad3b912
Improve dates formatting
mskwr Jan 30, 2023
a6e47ce
Improve dates formatting
mskwr Jan 30, 2023
c8c25cc
Use iterators everywhere I can
mskwr Jan 30, 2023
04fbe27
Use iterators everywhere I can
mskwr Jan 30, 2023
8789f27
Add tests for auth and strings
mskwr Jan 30, 2023
10042e0
Add tests for auth and strings
mskwr Jan 30, 2023
5103a62
Add tests for auth and strings
mskwr Jan 30, 2023
5ca54e1
Exclude retweets
mskwr Jan 30, 2023
65bc5a8
Exclude retweets
mskwr Jan 30, 2023
ec0eaa1
Exclude retweets
mskwr Jan 30, 2023
dd32089
Exclude retweets
mskwr Jan 30, 2023
59116d2
Exclude retweets
mskwr Jan 30, 2023
9acba7c
Exclude retweets
mskwr Jan 30, 2023
3a093c1
Exclude retweets
mskwr Jan 30, 2023
0a767d9
Add tests for requests
mskwr Feb 1, 2023
eaaf881
Add tests for requests
mskwr Feb 1, 2023
e295392
Add tests for requests
mskwr Feb 1, 2023
b083079
Add tests for requests
mskwr Feb 1, 2023
48c917d
Ignore tweets that can not be answered
mskwr Feb 4, 2023
28eaa0e
Ignore tweets that can not be answered
mskwr Feb 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "twitter-na-pewno-bot"
version = "0.1.0"
edition = "2021"
license = "MIT"
readme = "README.md"
authors = ["mskwr <[email protected]>"]
homepage = "https://github.com/mimuw-jnp2-rust/project-na-pewno-twitter-bot.git"
repository = "https://github.com/mimuw-jnp2-rust/project-na-pewno-twitter-bot.git"
description = "A bot drawing the attention of Poles to the most common spelling mistake they make."
keywords = ["twitter", "bot", "rust", "na-pewno"]

[dependencies]
twitter-v2 = "0.1.8"
tokio = { version = "1.24.2", features = ["macros"] }
time = "0.3.17"
rand = "0.8.5"
dotenv = "0.15.0"
21 changes: 21 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023 Michał Skwarek

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
46 changes: 31 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,40 @@
# Frobnicator (this is a template)
# na pewno bot for Twitter ([@napewnobot](https://twitter.com/napewnobot))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

niezbyt widać, żeby ten bot rzeczywiście działał...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Póki co bot celowo jest wyłączony. W obecnym stanie bardzo szybko otrzymałby shadowbana ze względu na ilość requestów i przede wszystkim takie same, generyczne odpowiedzi. Po shadowbanie użytkownicy np. nie dostawaliby powiadomień o odpowiedziach bota (dostał takiego shadowbana po pierwszym uruchomieniu, shadowban zniknął dopiero niedawno). Uruchomię go dzisiaj, po jego ukończeniu.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bot już został uruchomiony. Żeby nie dostać shadowbana i nie przekroczyć limitu, który tak naprawdę nikomu nie jest znany (wiadomo tylko, że można pisać 2400 Tweetów dziennie i jest to podzielone na mniejsze okresy czasu, ale czy jest to podzielone jednostajnie - tak naprawdę niewiadomo) nie działa on w nieskończonej pętli - jest raczej przeznaczony do "puszczenia" kilka razy dziennie. Tweety pisze co minutę.

[![Twitter URL](https://i.imgur.com/DPXcjpZ.png)](https://twitter.com/napewnobot)

## Authors
- Andrzej Głuszak (@agluszak on GitHub)
- Linus Torvalds (@torvalds on GitHub)
- Michał Skwarek ([@mskwr](https://github.com/mskwr))

## Description
Frobnicator is going to be a platformer game similar to Super Mario Bros made using Bevy game engine.
Statistics show that for many years, by far the most common spelling mistake made by Poles online is the phrase "na pewno" (which means "certainly"), incorrectly spelled as "napewno". On Twitter, this mistake is made by up to 1000 unique users every day. The job of the na pewno bot for Twitter is to improve these terrible statistics.

## Features
- map generator
- shooting
- enemy AI
- game state saving and loading
- scores
The bot provides the following features:
* finding all tweets containing "napewno"
* correcting spelling by automatically replying to these tweets
* maintaining statistics, including how many people per day made this mistake
* providing daily reports on the profile, including comparing results with the previous day

## Plan
In the first part we're going to implement the basics: movement, physics and shooting. The enemies will simply bounce from one edge of the platform to the other. There will be only a single map.
## Getting started
1. Sign up for the Twitter API to get the keys and tokens necessary for authorization. Set them as an environment variables.
2. Clone the repository.
```sh
git clone https://github.com/mimuw-jnp2-rust/twitter-na-pewno-bot.git
cd twitter-na-pewno-bot
```
3. Build the project.
```sh
cargo build --release
```
4. Run the project.
```sh
cargo run
```

In the second part we're going to add random map generator, saving/loading, scores and a more sophisticated AI.
## License
Distributed under the MIT License. See `LICENSE.txt` for more information.

## Libraries
- Bevy
- Serde (for serialization)
- [twitter_v2](https://docs.rs/twitter-v2/latest/twitter_v2/)
- [tokio](https://docs.rs/tokio/latest/tokio/)
- [rand](https://docs.rs/rand/latest/rand/)
- [time](https://docs.rs/time/latest/time/)
- [dotenv](https://docs.rs/dotenv/latest/dotenv/)
40 changes: 40 additions & 0 deletions src/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use std::env::var;
use twitter_v2::authorization::{BearerToken, Oauth1aToken};
use twitter_v2::TwitterApi;

// Gets api from app context (Read).
pub fn get_api_app_context() -> TwitterApi<BearerToken> {
TwitterApi::new(BearerToken::new(
var("BEARER_TOKEN").expect("BEARER_TOKEN not found"),
))
}

// Gets api from user context (Read and Write).
pub fn get_api_user_context() -> TwitterApi<Oauth1aToken> {
TwitterApi::new(Oauth1aToken::new(
var("API_KEY").expect("API_KEY not found"),
var("API_SECRET").expect("API_SECRET not found"),
var("ACCESS_TOKEN").expect("ACCESS_TOKEN not found"),
var("ACCESS_SECRET").expect("ACCESS_SECRET not found"),
))
}

#[cfg(test)]
mod tests {
use super::*;
use twitter_v2::Result;

#[tokio::test]
async fn test_get_api_app_context() -> Result<()> {
dotenv::dotenv().expect(".env file should be readable");
assert!(get_api_app_context().with_user_ctx().await.is_err());
Ok(())
}

#[tokio::test]
async fn test_get_api_user_context() -> Result<()> {
dotenv::dotenv().expect(".env file should be readable");
assert!(get_api_user_context().with_user_ctx().await.is_ok());
Ok(())
}
}
79 changes: 79 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
mod auth;
mod requests;
mod strings;

use crate::requests::{
count_tweets_with_mistake, get_initial_tweet, get_latest_tweet, get_my_user_id,
get_my_username, get_name_by_id, get_tweets_with_mistake, get_username_by_id,
post_reply_with_message, post_tweet_with_message,
};
use crate::strings::{
extract_statistics, generate_reply, generate_tweet, print_end_message, print_reply_message,
print_start_message, print_update_message,
};

use std::thread::sleep;
use std::time::Duration;
use time::OffsetDateTime;

// Due to the limit of 100 Tweets per hour.
const REQUEST_TIMEOUT_SECS: u64 = 60;

#[tokio::main]
async fn main() {
// Load environment variables from .env file.
dotenv::dotenv().expect(".env file should be readable");
print_start_message();

let my_id = get_my_user_id().await.expect("invalid authorization");
let my_username = get_my_username().await.expect("invalid authorization");
let my_latest_tweet = get_latest_tweet(my_id).await;

// All time variables are in UTC.
let cur_date = OffsetDateTime::now_utc().date();
let prev_date = cur_date.previous_day().expect("invalid date");

// Post daily updates with statistics on the profile.
if let Some(tweet) = my_latest_tweet {
let last_date = tweet.created_at.map(|t| t.date());

// Do not post anything if update was already made today.
if last_date != Some(cur_date) {
let cur_stat = count_tweets_with_mistake(&prev_date).await;
// Only extract previous stats if update was made on the previous day.
let prev_stat = if last_date == cur_date.previous_day() {
extract_statistics(tweet.text.as_str()).unwrap_or(0)
} else {
0
};

let msg = generate_tweet(prev_stat, cur_stat);
post_tweet_with_message(msg).await;
print_update_message(my_username);
}
} else {
// No updates on the profile yet.
let cur_stat = count_tweets_with_mistake(&prev_date).await;
let msg = generate_tweet(0, cur_stat);
post_tweet_with_message(msg).await;
print_update_message(my_username);
}

let initial_tweet_id = get_initial_tweet(my_id).await;
let tweets_with_mistake = get_tweets_with_mistake(initial_tweet_id).await;

// Can not use iterator here because of instability of async closures.
for tweet in tweets_with_mistake {
let id = tweet.author_id.expect("invalid user");
let username = get_username_by_id(id).await.expect("invalid user");
let name = get_name_by_id(id).await.expect("invalid user");
let msg = generate_reply(name.as_str());
post_reply_with_message(tweet.id, msg).await;
print_reply_message(tweet.id, username);

// Avoid shadowban and never exceed the limit of posts.
sleep(Duration::from_secs(REQUEST_TIMEOUT_SECS));
}

print_end_message();
}
Loading