mirror of
				https://github.com/akaessens/NoFbEventScraper
				synced 2025-06-05 23:29:13 +02:00 
			
		
		
		
	fix event info hiding after activity restore (closes #23), add comments
This commit is contained in:
		| @@ -60,6 +60,10 @@ public class EventAdapter extends | ||||
|         // Set item views based on your views and data model | ||||
|         holder.text_view_event_name.setText(event.name); | ||||
|  | ||||
|         /* | ||||
|          * initialize all text views with event information | ||||
|          * hide fields and image views if no information is available | ||||
|          */ | ||||
|         if (!event.location.equals("")) { | ||||
|             holder.text_view_event_location.setText(event.location); | ||||
|         } else { | ||||
| @@ -86,7 +90,6 @@ public class EventAdapter extends | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
|         if (!event.description.equals("")) { | ||||
|             holder.text_view_event_description.setText(event.description); | ||||
|         } else { | ||||
| @@ -120,13 +123,14 @@ public class EventAdapter extends | ||||
|         }; | ||||
|         holder.image_view_event_location.setOnClickListener(location_click_listener); | ||||
|         holder.text_view_event_location.setOnClickListener(location_click_listener); | ||||
|  | ||||
|         /* | ||||
|          * Add to calendar button: launch calendar application with current event | ||||
|          */ | ||||
|         holder.button_add_to_calendar.setOnClickListener(new View.OnClickListener() { | ||||
|             @Override | ||||
|             public void onClick(View view) { | ||||
|  | ||||
|                 // calendar event intent expects epoch time format | ||||
|                 Long start_epoch = dateTimeToEpoch(event.start_date); | ||||
|                 Long end_epoch = dateTimeToEpoch(event.end_date); | ||||
|  | ||||
| @@ -163,7 +167,7 @@ public class EventAdapter extends | ||||
|         }); | ||||
|  | ||||
|         /* | ||||
|          * Image dialog | ||||
|          * Image preview click creates fullscreen dialog | ||||
|          */ | ||||
|  | ||||
|         View.OnClickListener listener = new View.OnClickListener() { | ||||
| @@ -198,7 +202,6 @@ public class EventAdapter extends | ||||
|                         }); | ||||
|  | ||||
|  | ||||
|  | ||||
|             } | ||||
|         }; | ||||
|         holder.image_view_event_image.setOnClickListener(listener); | ||||
| @@ -212,6 +215,9 @@ public class EventAdapter extends | ||||
|         return events.size(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * access item view elements via holder class | ||||
|      */ | ||||
|     public static class ViewHolder extends RecyclerView.ViewHolder { | ||||
|  | ||||
|         protected TextView text_view_event_name; | ||||
|   | ||||
| @@ -163,6 +163,7 @@ public class FbEventScraper extends AsyncTask<Void, Void, Void> { | ||||
|  | ||||
|                 JSONObject reader = new JSONObject(json); | ||||
|  | ||||
|                 // get all fields from json event information | ||||
|                 name = readFromJson(reader, "name"); | ||||
|                 start_date = parseToDate(readFromJson(reader, "startDate")); | ||||
|                 end_date = parseToDate(readFromJson(reader, "endDate")); | ||||
| @@ -170,6 +171,7 @@ public class FbEventScraper extends AsyncTask<Void, Void, Void> { | ||||
|                 location = fixLocation(readFromJson(reader, "location")); | ||||
|                 image_url = readFromJson(reader, "image"); | ||||
|  | ||||
|                 // try to find a high-res image | ||||
|                 try { | ||||
|                     image_url = document.select("div[id=event_header_primary]") | ||||
|                             .select("img").first().attr("src"); | ||||
| @@ -177,6 +179,7 @@ public class FbEventScraper extends AsyncTask<Void, Void, Void> { | ||||
|                 } | ||||
|  | ||||
|             } catch (JSONException | NullPointerException e) { | ||||
|                 // json event information mot found. get at least title and image | ||||
|                 name = document.title(); | ||||
|                 description = scraper.main.get().getString(R.string.error_scraping); | ||||
|                 try { | ||||
| @@ -186,9 +189,6 @@ public class FbEventScraper extends AsyncTask<Void, Void, Void> { | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|             this.event = new FbEvent(url, name, start_date, end_date, description, location, image_url); | ||||
|  | ||||
|         } catch (IOException e) { | ||||
|   | ||||
| @@ -22,7 +22,7 @@ public class FbPageScraper extends AsyncTask<Void, Void, Void> { | ||||
|     private FbScraper scraper; | ||||
|     private int error; | ||||
|     private String url; | ||||
|     private List<String> event_links = new ArrayList<String>(); | ||||
|     private List<String> event_links = new ArrayList<>(); | ||||
|  | ||||
|     /** | ||||
|      * Constructor with reference to scraper to return results. | ||||
| @@ -58,6 +58,9 @@ public class FbPageScraper extends AsyncTask<Void, Void, Void> { | ||||
|                     throw new IOException(); | ||||
|                 } | ||||
|  | ||||
|                 /* | ||||
|                  * get all event id's from current url and add to the list | ||||
|                  */ | ||||
|                 String regex = "(/events/[0-9]*)(/\\?event_time_id=[0-9]*)?"; | ||||
|  | ||||
|                 List<String> event_links_href = document | ||||
| @@ -68,13 +71,16 @@ public class FbPageScraper extends AsyncTask<Void, Void, Void> { | ||||
|                     this.event_links.add("https://www.facebook.com" + link); | ||||
|                 } | ||||
|  | ||||
|                 /* | ||||
|                  * check if more events should scraped | ||||
|                  */ | ||||
|                 SharedPreferences shared_prefs = PreferenceManager | ||||
|                         .getDefaultSharedPreferences(scraper.main.get()); | ||||
|  | ||||
|                 int max = shared_prefs.getInt("page_event_max", 5); | ||||
|  | ||||
|                 if (event_links.size() < max) { | ||||
|  | ||||
|                     // find "next page | ||||
|                     try { | ||||
|                         String next_url = document | ||||
|                                 .getElementsByAttributeValueMatching("href", "has_more=1") | ||||
|   | ||||
| @@ -14,15 +14,12 @@ import java.util.List; | ||||
| import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
|  | ||||
| import static com.akdev.nofbeventscraper.FbEvent.createEventList; | ||||
|  | ||||
| public class FbScraper { | ||||
|  | ||||
|     protected List<FbEvent> events; | ||||
|     protected List<AsyncTask> tasks; | ||||
|     protected WeakReference<MainActivity> main; // no context leak with WeakReference | ||||
|     url_type_enum url_type = url_type_enum.EVENT; | ||||
|     private String input_url; | ||||
|     protected WeakReference<MainActivity> main; // no context leak with WeakReference | ||||
|  | ||||
|     /** | ||||
|      * Constructor with WeakReference to the main activity, to add events. | ||||
| @@ -33,10 +30,18 @@ public class FbScraper { | ||||
|     FbScraper(WeakReference<MainActivity> main, String input_url) { | ||||
|         this.main = main; | ||||
|         this.input_url = input_url; | ||||
|         this.events = createEventList(); | ||||
|         this.tasks = new ArrayList<>(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Checks if valid URL, | ||||
|      * strips the facebook page id from the input link and create an URL that can be scraped from. | ||||
|      * | ||||
|      * @param url input URL | ||||
|      * @return new mbasic url that can be scraped for event id's | ||||
|      * @throws URISyntaxException    if page not found | ||||
|      * @throws MalformedURLException | ||||
|      */ | ||||
|     protected String getPageUrl(String url) throws URISyntaxException, MalformedURLException { | ||||
|  | ||||
|         // check for url format | ||||
| @@ -48,10 +53,11 @@ public class FbScraper { | ||||
|         Matcher matcher = pattern.matcher(url); | ||||
|  | ||||
|         if (matcher.find()) { | ||||
|  | ||||
|             //only mbasic does have event ids displayed in HTML | ||||
|             String url_prefix = "https://mbasic.facebook.com/"; | ||||
|             String url_suffix = "?v=events"; | ||||
|  | ||||
|             // create URL | ||||
|             return url_prefix + matcher.group(3) + url_suffix; | ||||
|  | ||||
|         } else { | ||||
| @@ -60,7 +66,7 @@ public class FbScraper { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Strips the facebook event link of the input url. | ||||
|      * Strips the facebook event link from the input event url. | ||||
|      * | ||||
|      * @param url input url | ||||
|      * @return facebook event url String if one was found | ||||
| @@ -98,12 +104,40 @@ public class FbScraper { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * cancel vestigial async tasks | ||||
|      */ | ||||
|     void killAllTasks() { | ||||
|  | ||||
|         if (!tasks.isEmpty()) { | ||||
|             for (AsyncTask task : tasks) { | ||||
|                 try { | ||||
|                     task.cancel(true); | ||||
|                     task = null; | ||||
|                 } catch (Exception e) { | ||||
|                     e.printStackTrace(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * start an EventScraper async task and add to tasks list | ||||
|      * | ||||
|      * @param event_url | ||||
|      */ | ||||
|     void scrapeEvent(String event_url) { | ||||
|         FbEventScraper scraper = new FbEventScraper(this, event_url); | ||||
|         tasks.add(scraper); | ||||
|         scraper.execute(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Callback for finished EventSCraper async task | ||||
|      * | ||||
|      * @param event Contains event information if scraping successful | ||||
|      * @param error resId for error message | ||||
|      */ | ||||
|     void scrapeEventResultCallback(FbEvent event, int error) { | ||||
|  | ||||
|         if (event != null) { | ||||
| @@ -115,20 +149,10 @@ public class FbScraper { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * cancel vestigial async tasks | ||||
|      * start a page scraper and add to list of tasks | ||||
|      * | ||||
|      * @param page_url | ||||
|      */ | ||||
|     void killAllTasks() { | ||||
|  | ||||
|         try { | ||||
|             for (AsyncTask task : tasks) { | ||||
|                 task.cancel(true); | ||||
|                 task = null; | ||||
|             } | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void scrapePage(String page_url) { | ||||
|         FbPageScraper scraper = new FbPageScraper(this, page_url); | ||||
|  | ||||
| @@ -136,6 +160,12 @@ public class FbScraper { | ||||
|         scraper.execute(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Callback for page scraper async task | ||||
|      * | ||||
|      * @param event_urls List of event urls scraped from the event | ||||
|      * @param error      resId of error message if task list is empty | ||||
|      */ | ||||
|     protected void scrapePageResultCallback(List<String> event_urls, int error) { | ||||
|  | ||||
|         if (event_urls.size() > 0) { | ||||
| @@ -153,8 +183,12 @@ public class FbScraper { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Start scraping input url | ||||
|      */ | ||||
|     void run() { | ||||
|  | ||||
|         // check if input url is an event | ||||
|         try { | ||||
|             String event_url = getEventUrl(input_url); | ||||
|             url_type = url_type_enum.EVENT; | ||||
| @@ -165,7 +199,7 @@ public class FbScraper { | ||||
|         } catch (URISyntaxException | MalformedURLException e) { | ||||
|             url_type = url_type_enum.INVALID; | ||||
|         } | ||||
|  | ||||
|         // check if input url is a page | ||||
|         try { | ||||
|             String page_url = getPageUrl(input_url); | ||||
|             url_type = url_type_enum.PAGE; | ||||
| @@ -177,6 +211,6 @@ public class FbScraper { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     // enum for storing url type in this class | ||||
|     enum url_type_enum {EVENT, PAGE, INVALID} | ||||
| } | ||||
| @@ -1,11 +1,10 @@ | ||||
| package com.akdev.nofbeventscraper; | ||||
|  | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
|  | ||||
| import android.content.Intent; | ||||
| import android.net.Uri; | ||||
| import android.os.Bundle; | ||||
|  | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
|  | ||||
| public class IntentReceiver extends AppCompatActivity { | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -5,7 +5,6 @@ import android.content.ClipboardManager; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.content.SharedPreferences; | ||||
| import android.net.Uri; | ||||
| import android.os.Bundle; | ||||
| import android.view.KeyEvent; | ||||
| import android.view.Menu; | ||||
| @@ -65,17 +64,24 @@ public class MainActivity extends AppCompatActivity { | ||||
|         return list; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Callback for Restoring data | ||||
|     /* | ||||
|      * On resume from other activities, e.g. settings | ||||
|      */ | ||||
|     @Override | ||||
|     public void onResume() { | ||||
|         super.onResume(); | ||||
|  | ||||
|         /* | ||||
|          * Clear events after saved events deleted from settings | ||||
|          */ | ||||
|         if (getSavedEvents().isEmpty()) { | ||||
|             events.clear(); | ||||
|         events.addAll(getSavedEvents()); | ||||
|             adapter.notifyDataSetChanged(); | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Intent from IntentReceiver - read only once | ||||
|          */ | ||||
|         Intent intent = getIntent(); | ||||
|         String data = intent.getStringExtra("InputLink"); | ||||
|  | ||||
| @@ -209,7 +215,7 @@ public class MainActivity extends AppCompatActivity { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * launch the FbScraper asynchronous task with the current text in the input text field. | ||||
|      * launch the FbScraper with the current text in the input text field. | ||||
|      */ | ||||
|     public void startScraping() { | ||||
|  | ||||
| @@ -222,6 +228,12 @@ public class MainActivity extends AppCompatActivity { | ||||
|         scraper.run(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * manage Helper text on uri_input | ||||
|      * | ||||
|      * @param str What should be displayed | ||||
|      * @param error True if should be displayed as error | ||||
|      */ | ||||
|     public void input_helper(String str, boolean error) { | ||||
|  | ||||
|         if (str == null) { | ||||
| @@ -255,14 +267,21 @@ public class MainActivity extends AppCompatActivity { | ||||
|         // Inflate the menu; this adds items to the action bar if it is present. | ||||
|         getMenuInflater().inflate(R.menu.menu_main, menu); | ||||
|  | ||||
|         /* | ||||
|          * Display icons, restricted API, maybe find other solution? | ||||
|          */ | ||||
|         if (menu instanceof MenuBuilder) { | ||||
|             MenuBuilder m = (MenuBuilder) menu; | ||||
|             //noinspection RestrictedApi | ||||
|             m.setOptionalIconsVisible(true); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Dispatch menu item to new activity | ||||
|      * @param item | ||||
|      * @return | ||||
|      */ | ||||
|     @Override | ||||
|     public boolean onOptionsItemSelected(MenuItem item) { | ||||
|  | ||||
|   | ||||
| @@ -1,20 +1,15 @@ | ||||
| package com.akdev.nofbeventscraper; | ||||
|  | ||||
| import android.content.SharedPreferences; | ||||
| import android.graphics.Color; | ||||
| import android.os.Bundle; | ||||
| import android.view.View; | ||||
| import android.widget.TextView; | ||||
| import android.widget.Toast; | ||||
|  | ||||
| import androidx.appcompat.app.ActionBar; | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
| import androidx.preference.Preference; | ||||
| import androidx.preference.PreferenceFragmentCompat; | ||||
| import androidx.preference.PreferenceManager; | ||||
|  | ||||
| import com.google.android.material.snackbar.Snackbar; | ||||
| import com.google.gson.Gson; | ||||
|  | ||||
| public class SettingsActivity extends AppCompatActivity { | ||||
|  | ||||
| @@ -37,6 +32,9 @@ public class SettingsActivity extends AppCompatActivity { | ||||
|         public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { | ||||
|             setPreferencesFromResource(R.xml.root_preferences, rootKey); | ||||
|  | ||||
|             /* | ||||
|              * reset events click action: delete saved events and display snackbar | ||||
|              */ | ||||
|             Preference button = findPreference("event_reset"); | ||||
|             if (button != null) { | ||||
|                 button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user