diff options
-rw-r--r-- | .gitignore | 6 | ||||
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | CMakeLists.txt | 16 | ||||
-rw-r--r-- | lunatic.cpp | 84 | ||||
-rw-r--r-- | scrape.rb | 38 | ||||
m--------- | vendor/libtwittercpp | 0 |
6 files changed, 147 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae9dcf9 --- /dev/null +++ b/.gitignore | |||
@@ -0,0 +1,6 @@ | |||
1 | .AppleDouble | ||
2 | .DS_Store | ||
3 | CMakeCache.txt | ||
4 | Makefile | ||
5 | cmake_install.cmake | ||
6 | CMakeFiles | ||
diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..b7a969a --- /dev/null +++ b/.gitmodules | |||
@@ -0,0 +1,3 @@ | |||
1 | [submodule "vendor/libtwittercpp"] | ||
2 | path = vendor/libtwittercpp | ||
3 | url = git@github.com:hatkirby/libtwittercpp | ||
diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..55a671b --- /dev/null +++ b/CMakeLists.txt | |||
@@ -0,0 +1,16 @@ | |||
1 | cmake_minimum_required (VERSION 3.1) | ||
2 | project (lunatic) | ||
3 | |||
4 | add_subdirectory(vendor/libtwittercpp) | ||
5 | |||
6 | find_package(PkgConfig) | ||
7 | pkg_check_modules(yaml-cpp yaml-cpp REQUIRED) | ||
8 | |||
9 | include_directories( | ||
10 | vendor/libtwittercpp/src | ||
11 | ${yaml-cpp_INCLUDE_DIRS}) | ||
12 | |||
13 | add_executable(lunatic lunatic.cpp) | ||
14 | set_property(TARGET lunatic PROPERTY CXX_STANDARD 11) | ||
15 | set_property(TARGET lunatic PROPERTY CXX_STANDARD_REQUIRED ON) | ||
16 | target_link_libraries(lunatic ${yaml-cpp_LIBRARIES} twitter++) \ No newline at end of file | ||
diff --git a/lunatic.cpp b/lunatic.cpp new file mode 100644 index 0000000..2438788 --- /dev/null +++ b/lunatic.cpp | |||
@@ -0,0 +1,84 @@ | |||
1 | #include <yaml-cpp/yaml.h> | ||
2 | #include <iostream> | ||
3 | #include <random> | ||
4 | #include <fstream> | ||
5 | #include <twitter.h> | ||
6 | #include <chrono> | ||
7 | #include <thread> | ||
8 | |||
9 | int main(int argc, char** argv) | ||
10 | { | ||
11 | if (argc != 2) | ||
12 | { | ||
13 | std::cout << "usage: lunatic [configfile]" << std::endl; | ||
14 | return -1; | ||
15 | } | ||
16 | |||
17 | std::string configfile(argv[1]); | ||
18 | YAML::Node config = YAML::LoadFile(configfile); | ||
19 | |||
20 | twitter::auth auth; | ||
21 | auth.setConsumerKey(config["consumer_key"].as<std::string>()); | ||
22 | auth.setConsumerSecret(config["consumer_secret"].as<std::string>()); | ||
23 | auth.setAccessKey(config["access_key"].as<std::string>()); | ||
24 | auth.setAccessSecret(config["access_secret"].as<std::string>()); | ||
25 | |||
26 | twitter::client client(auth); | ||
27 | |||
28 | std::random_device randomDevice; | ||
29 | std::mt19937 rng(randomDevice()); | ||
30 | |||
31 | for (;;) | ||
32 | { | ||
33 | std::cout << "Generating tweet" << std::endl; | ||
34 | |||
35 | // Reload achievements list every time in case it has been updated | ||
36 | std::vector<std::string> achievements; | ||
37 | std::ifstream datafile(config["achievements"].as<std::string>()); | ||
38 | if (!datafile.is_open()) | ||
39 | { | ||
40 | std::cout << "Could not find achievements file." << std::endl; | ||
41 | return 1; | ||
42 | } | ||
43 | |||
44 | std::string line; | ||
45 | while (getline(datafile, line)) | ||
46 | { | ||
47 | if (line.back() == '\r') | ||
48 | { | ||
49 | line.pop_back(); | ||
50 | } | ||
51 | |||
52 | achievements.push_back(line); | ||
53 | } | ||
54 | |||
55 | std::uniform_int_distribution<int> dist(0, achievements.size() - 1); | ||
56 | std::string achievement = achievements[dist(rng)]; | ||
57 | |||
58 | std::string header; | ||
59 | if (std::bernoulli_distribution(1.0 / 50.0)(rng)) | ||
60 | { | ||
61 | header = "YOU GOT A MULTI MOON!"; | ||
62 | } else { | ||
63 | header = "YOU GOT A MOON!"; | ||
64 | } | ||
65 | |||
66 | std::string action = header + "\n" + achievement; | ||
67 | action.resize(140); | ||
68 | |||
69 | try | ||
70 | { | ||
71 | client.updateStatus(action); | ||
72 | } catch (const twitter::twitter_error& e) | ||
73 | { | ||
74 | std::cout << "Twitter error: " << e.what() << std::endl; | ||
75 | } | ||
76 | |||
77 | std::cout << action << std::endl; | ||
78 | std::cout << "Waiting" << std::endl; | ||
79 | |||
80 | std::this_thread::sleep_for(std::chrono::hours(3)); | ||
81 | |||
82 | std::cout << std::endl; | ||
83 | } | ||
84 | } | ||
diff --git a/scrape.rb b/scrape.rb new file mode 100644 index 0000000..5d62e89 --- /dev/null +++ b/scrape.rb | |||
@@ -0,0 +1,38 @@ | |||
1 | require 'json' | ||
2 | require 'nokogiri' | ||
3 | require 'open-uri' | ||
4 | require 'yaml' | ||
5 | |||
6 | config = YAML.load(open("config.yml")) | ||
7 | usernames = config["usernames"] | ||
8 | |||
9 | achieves = usernames.map do |username| | ||
10 | page = Nokogiri::HTML(open("https://steamcommunity.com/id/#{username}/games/?tab=all")) | ||
11 | script = page.css(".responsive_page_template_content script").text[18..-1] | ||
12 | data = JSON.parse(script[0..script.index(";\r\n\t\t")-1]) | ||
13 | ids = data.map { |d| d["appid"] } | ||
14 | |||
15 | ids.map do |id| | ||
16 | achsp = Nokogiri::HTML(open("https://steamcommunity.com/id/#{username}/stats/#{id}/")) | ||
17 | achsp.css(".achieveTxt .achieveUnlockTime + h3").map { |d| d.text } | ||
18 | end | ||
19 | end.flatten | ||
20 | |||
21 | if File.exists?("achieves.txt") | ||
22 | already = File.read("achieves.txt").split("\n") | ||
23 | all_achieves = achieves + already | ||
24 | else | ||
25 | all_achieves = achieves | ||
26 | end | ||
27 | |||
28 | all_achieves.sort! | ||
29 | all_achieves.uniq! | ||
30 | |||
31 | if config.key? "blacklist" | ||
32 | blacklist = File.read(config["blacklist"]).split("\n") | ||
33 | all_achieves.reject! { |l| blacklist.include? l } | ||
34 | end | ||
35 | |||
36 | File.open("achieves.txt", "w") do |f| | ||
37 | f << all_achieves.join("\n") | ||
38 | end | ||
diff --git a/vendor/libtwittercpp b/vendor/libtwittercpp new file mode 160000 | |||
Subproject d1d20515281e32b23657762e72bf37dcff14f0a | |||